@azure-tools/typespec-rust 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/src/codegen/clients.d.ts.map +1 -1
  2. package/dist/src/codegen/clients.js +203 -178
  3. package/dist/src/codegen/clients.js.map +1 -1
  4. package/dist/src/codegen/context.d.ts.map +1 -1
  5. package/dist/src/codegen/context.js +27 -11
  6. package/dist/src/codegen/context.js.map +1 -1
  7. package/dist/src/codegen/helpers.d.ts +5 -2
  8. package/dist/src/codegen/helpers.d.ts.map +1 -1
  9. package/dist/src/codegen/helpers.js +22 -16
  10. package/dist/src/codegen/helpers.js.map +1 -1
  11. package/dist/src/codegen/mod.d.ts.map +1 -1
  12. package/dist/src/codegen/mod.js +4 -2
  13. package/dist/src/codegen/mod.js.map +1 -1
  14. package/dist/src/codemodel/client.d.ts +38 -9
  15. package/dist/src/codemodel/client.d.ts.map +1 -1
  16. package/dist/src/codemodel/client.js +15 -3
  17. package/dist/src/codemodel/client.js.map +1 -1
  18. package/dist/src/codemodel/types.d.ts +6 -6
  19. package/dist/src/codemodel/types.js +3 -3
  20. package/dist/src/emitter.d.ts.map +1 -1
  21. package/dist/src/emitter.js +9 -1
  22. package/dist/src/emitter.js.map +1 -1
  23. package/dist/src/lib.d.ts +9 -9
  24. package/dist/src/lib.js +3 -3
  25. package/dist/src/lib.js.map +1 -1
  26. package/dist/src/tcgcadapter/adapter.d.ts +6 -0
  27. package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
  28. package/dist/src/tcgcadapter/adapter.js +99 -63
  29. package/dist/src/tcgcadapter/adapter.js.map +1 -1
  30. package/dist/src/tcgcadapter/helpers.d.ts +0 -17
  31. package/dist/src/tcgcadapter/helpers.d.ts.map +1 -1
  32. package/dist/src/tcgcadapter/helpers.js +1 -71
  33. package/dist/src/tcgcadapter/helpers.js.map +1 -1
  34. package/dist/src/tcgcadapter/naming.d.ts +16 -0
  35. package/dist/src/tcgcadapter/naming.d.ts.map +1 -1
  36. package/dist/src/tcgcadapter/naming.js +36 -0
  37. package/dist/src/tcgcadapter/naming.js.map +1 -1
  38. package/package.json +22 -22
@@ -1 +1 @@
1
- {"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAG9C,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/B,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,aAAa,GAAG,SAAS,CA2QxE"}
1
+ {"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAG9C,yBAAyB;AACzB,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/B,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,aAAa,GAAG,SAAS,CAuQxE"}
@@ -82,18 +82,17 @@ export function emitClients(crate) {
82
82
  body += `${indent.get()}let options = options.unwrap_or_default();\n`;
83
83
  // by convention, the endpoint param is always the first ctor param
84
84
  const endpointParamName = constructor.params[0].name;
85
- body += `${indent.push().get()}let mut ${endpointParamName} = Url::parse(${endpointParamName})?;\n`;
85
+ body += `${indent.push().get()}let ${client.constructable.endpoint ? 'mut ' : ''}${endpointParamName} = Url::parse(${endpointParamName})?;\n`;
86
86
  body += `${indent.get()}${helpers.buildIfBlock(indent, {
87
87
  condition: `!${endpointParamName}.scheme().starts_with("http")`,
88
- body: (indent) => `${indent.get()}return Err(azure_core::Error::message(azure_core::error::ErrorKind::Other, format!("{${endpointParamName}} must use http(s)")));\n`,
88
+ body: (indent) => `${indent.get()}return Err(azure_core::Error::with_message(azure_core::error::ErrorKind::Other, format!("{${endpointParamName}} must use http(s)")));\n`,
89
89
  })}`;
90
- body += `${indent.get()}${endpointParamName}.set_query(None);\n`;
91
90
  // construct the supplemental path and join it to the endpoint
92
91
  if (client.constructable.endpoint) {
93
92
  const supplementalEndpoint = client.constructable.endpoint;
94
93
  body += `${indent.get()}let mut host = String::from("${supplementalEndpoint.path}");\n`;
95
94
  for (const param of supplementalEndpoint.parameters) {
96
- body += `${indent.get()}host = host.replace("{${param.segment}}", ${getClientEndpointParamValue(param)});\n`;
95
+ body += `${indent.get()}host = host.replace("{${param.segment}}", ${getClientSupplementalEndpointParamValue(param)});\n`;
97
96
  }
98
97
  body += `${indent.push().get()}${endpointParamName} = ${endpointParamName}.join(&host)?;\n`;
99
98
  }
@@ -109,15 +108,11 @@ export function emitClients(crate) {
109
108
  // exclude endpoint params as they aren't propagated to clients (they're consumed when creating the complete endpoint)
110
109
  const sortedParams = values([...constructor.params]
111
110
  .sort((a, b) => { return helpers.sortAscending(a.name, b.name); }))
112
- .where((each) => each.kind !== 'clientEndpoint').toArray();
111
+ .where((each) => each.kind !== 'clientSupplementalEndpoint' && each.kind !== 'clientCredential').toArray();
113
112
  for (const param of sortedParams) {
114
113
  if (param.optional) {
115
114
  continue;
116
115
  }
117
- else if (isCredential(param.type)) {
118
- // credential params aren't persisted on the client so skip them
119
- continue;
120
- }
121
116
  if (!client.fields.find((v) => { return v.name === param.name; })) {
122
117
  throw new CodegenError('InternalError', `didn't find field in client ${client.name} for param ${param.name}`);
123
118
  }
@@ -287,7 +282,9 @@ function getMethodOptions(crate) {
287
282
  }
288
283
  body += '}\n\n'; // end options
289
284
  if (method.kind === 'pageable' || method.kind === 'lro') {
290
- body += `impl ${helpers.getTypeDeclaration(method.options.type, true)} {\n`;
285
+ body += `impl ${helpers.getTypeDeclaration(method.options.type, 'anonymous')} {\n`;
286
+ const wrappedTypeName = helpers.wrapInBackTicks(helpers.getTypeDeclaration(method.options.type, 'omit'));
287
+ body += `${indent.get()}/// Transforms this [${wrappedTypeName}] into a new ${wrappedTypeName} that owns the underlying data, cloning it if necessary.\n`;
291
288
  body += `${indent.get()}pub fn into_owned(self) -> ${method.options.type.name}<'static> {\n`;
292
289
  body += `${indent.push().get()}${method.options.type.name} {\n`;
293
290
  indent.push();
@@ -419,7 +416,7 @@ function getMethodParamsSig(method, use) {
419
416
  paramsSig.push(`${param.name}: ${formatParamTypeName(param)}`);
420
417
  }
421
418
  }
422
- paramsSig.push(`options: ${helpers.getTypeDeclaration(method.options, true)}`);
419
+ paramsSig.push(`options: ${helpers.getTypeDeclaration(method.options, 'anonymous')}`);
423
420
  }
424
421
  return paramsSig.join(', ');
425
422
  }
@@ -848,10 +845,26 @@ function applyHeaderParams(indent, use, method, paramGroups, inClosure) {
848
845
  // we have some special handling for the header continuation token.
849
846
  // if we have a token value, i.e. from the next page, then use that value.
850
847
  // if not, then check if an optional token value was provided.
848
+ body += `${indent.get()}let ${headerParam.name} = ` + helpers.buildMatch(indent, headerParam.name, [
849
+ {
850
+ pattern: `PagerState::More(${headerParam.name})`,
851
+ body: (indent) => `${indent.get()}&Some(${headerParam.name})\n`,
852
+ },
853
+ {
854
+ pattern: 'PagerState::Initial',
855
+ body: (indent) => `${indent.get()}&options.${headerParam.name}\n`,
856
+ }
857
+ ]) + ';\n';
851
858
  body += indent.get() + helpers.buildIfBlock(indent, {
852
- condition: `let Some(${headerParam.name}) = ${headerParam.name}.or_else(|| options.${headerParam.name}.clone())`,
859
+ condition: `let Some(${headerParam.name}) = ${headerParam.name}`,
853
860
  body: (indent) => `${indent.get()}request.insert_header("${headerParam.header}", ${headerParam.name});\n`,
854
- });
861
+ }) + '\n';
862
+ continue;
863
+ }
864
+ if (isOptionalContentTypeHeader(headerParam)) {
865
+ // when the body is optional, the Content-Type header
866
+ // will be set IFF the optional body param is not None.
867
+ // this logic happens elsewhere so we skip it here.
855
868
  continue;
856
869
  }
857
870
  body += getParamValueHelper(indent, headerParam, inClosure, () => {
@@ -869,6 +882,10 @@ function applyHeaderParams(indent, use, method, paramGroups, inClosure) {
869
882
  }
870
883
  return body;
871
884
  }
885
+ /** type guard to determine if headerParam is an optional Content-Type header */
886
+ function isOptionalContentTypeHeader(headerParam) {
887
+ return headerParam.kind === 'headerScalar' && headerParam.optional && headerParam.header.toLowerCase() === 'content-type';
888
+ }
872
889
  /**
873
890
  * emits the code for building the HTTP request.
874
891
  * assumes that there's a local var 'url' which is the Url.
@@ -889,7 +906,7 @@ function constructRequest(indent, use, method, paramGroups, inClosure, cloneUrl
889
906
  let optionalContentTypeParam;
890
907
  for (const headerParam of paramGroups.header) {
891
908
  // if the content-type header is optional, we need to emit it inside the "if let Some(body)" clause below.
892
- if (headerParam.kind === 'headerScalar' && headerParam.optional && headerParam.header.toLowerCase() === 'content-type') {
909
+ if (isOptionalContentTypeHeader(headerParam)) {
893
910
  optionalContentTypeParam = headerParam;
894
911
  }
895
912
  }
@@ -934,27 +951,6 @@ function constructRequest(indent, use, method, paramGroups, inClosure, cloneUrl
934
951
  }
935
952
  return body;
936
953
  }
937
- /**
938
- * Return an error if a local RawResponse variable "rsp" has a non-success status code.
939
- * @param use the use statement builder currently in scope
940
- * @param indent the indentation helper currently in scope
941
- * @returns code to return an error if the status code of "rsp" doesn't indicate success
942
- */
943
- function errIfNotSuccessResponse(use, indent) {
944
- use.add('azure_core', 'Error', 'Result');
945
- use.add('azure_core::http::headers', 'ERROR_CODE');
946
- use.add('azure_core::error', 'ErrorKind', 'HttpError');
947
- return helpers.buildIfBlock(indent, {
948
- condition: '!rsp.status().is_success()',
949
- body: (indent) => {
950
- let body = `${indent.get()}let status = rsp.status();\n`;
951
- body += `${indent.get()}let http_error = HttpError::new(rsp, Some(ERROR_CODE)).await;\n`;
952
- body += `${indent.get()}let error_kind = ErrorKind::http_response(status, http_error.error_code().map(std::borrow::ToOwned::to_owned));\n`;
953
- body += `${indent.get()}return Err(Error::new(error_kind, http_error));\n`;
954
- return body;
955
- },
956
- });
957
- }
958
954
  /**
959
955
  * Returns 'mut ' if the Url local var needs to be mutable, else the empty string.
960
956
  * @param paramGroups the param groups associated with the Url being constructed.
@@ -1016,7 +1012,7 @@ function emitEmptyPathParamCheck(indent, param) {
1016
1012
  }
1017
1013
  return helpers.buildIfBlock(indent, {
1018
1014
  condition: `${param.name}${toString}.is_empty()`,
1019
- body: (indent) => `${indent.get()}return Err(azure_core::Error::message(azure_core::error::ErrorKind::Other, "parameter ${param.name} cannot be empty"));`,
1015
+ body: (indent) => `${indent.get()}return Err(azure_core::Error::with_message(azure_core::error::ErrorKind::Other, "parameter ${param.name} cannot be empty"));`,
1020
1016
  });
1021
1017
  }
1022
1018
  /**
@@ -1037,10 +1033,9 @@ function getAsyncMethodBody(indent, use, client, method) {
1037
1033
  body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}url = self.${getEndpointFieldName(client)}.clone();\n`;
1038
1034
  body += constructUrl(indent, use, method, paramGroups);
1039
1035
  body += constructRequest(indent, use, method, paramGroups, false);
1040
- body += `${indent.get()}let rsp = self.pipeline.send(&ctx, &mut request).await?;\n`;
1041
- body += errIfNotSuccessResponse(use, indent);
1036
+ body += `${indent.get()}let rsp = self.pipeline.send(&ctx, &mut request, ${getPipelineSendOptions(indent, use, method)}).await?;\n`;
1042
1037
  let rspInto = 'rsp.into()';
1043
- if (method.returns.type.kind === 'rawResponse') {
1038
+ if (method.returns.type.kind === 'bufResponse') {
1044
1039
  rspInto = 'rsp';
1045
1040
  }
1046
1041
  body += `${indent.get()}Ok(${rspInto})\n`;
@@ -1056,17 +1051,13 @@ function getAsyncMethodBody(indent, use, client, method) {
1056
1051
  * @returns the contents of the method body
1057
1052
  */
1058
1053
  function getPageableMethodBody(indent, use, client, method) {
1059
- if (!method.strategy) {
1060
- throw new CodegenError('InternalError', 'paged method with no strategy NYI');
1061
- }
1062
- const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
1063
1054
  use.add('azure_core::http', 'Method', 'Request', 'Url');
1064
1055
  use.add('azure_core::http::pager', 'PagerResult', 'PagerState');
1065
- use.add('azure_core', bodyFormat, 'Result');
1056
+ use.add('azure_core', 'Result');
1066
1057
  use.addForType(method.returns.type);
1067
1058
  use.addForType(helpers.unwrapType(method.returns.type));
1068
1059
  const paramGroups = getMethodParamGroup(method);
1069
- const urlVar = 'first_url';
1060
+ const urlVar = method.strategy ? 'first_url' : 'url';
1070
1061
  let body = checkEmptyRequiredPathParams(indent, paramGroups.path);
1071
1062
  body += 'let options = options.unwrap_or_default().into_owned();\n';
1072
1063
  body += `${indent.get()}let pipeline = self.pipeline.clone();\n`;
@@ -1075,139 +1066,163 @@ function getPageableMethodBody(indent, use, client, method) {
1075
1066
  if (paramGroups.apiVersion) {
1076
1067
  body += `${indent.get()}let ${paramGroups.apiVersion.name} = ${getHeaderPathQueryParamValue(use, paramGroups.apiVersion, true)}.clone();\n`;
1077
1068
  }
1078
- switch (method.strategy.kind) {
1079
- case 'continuationToken': {
1080
- const reqTokenParam = method.strategy.requestToken.name;
1081
- body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(move |${reqTokenParam}: PagerState<String>| {\n`;
1082
- body += `${indent.push().get()}let ${method.strategy.requestToken.kind === 'queryScalar' ? 'mut ' : ''}url = first_url.clone();\n`;
1083
- if (method.strategy.requestToken.kind === 'queryScalar') {
1084
- // if the url already contains the token query param,
1085
- // e.g. we started on some page, then we need to remove
1086
- // it before appending the token for the next page.
1087
- const reqTokenValue = method.strategy.requestToken.key;
1088
- body += `${indent.get()}${helpers.buildIfBlock(indent, {
1089
- condition: `let PagerState::More(${reqTokenParam}) = ${reqTokenParam}`,
1090
- body: (indent) => {
1091
- let body = indent.get() + helpers.buildIfBlock(indent, {
1092
- condition: `url.query_pairs().any(|(name, _)| name.eq("${reqTokenValue}"))`,
1093
- body: (indent) => {
1094
- let body = `${indent.get()}let mut new_url = url.clone();\n`;
1095
- body += `${indent.get()}new_url.query_pairs_mut().clear().extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("${reqTokenValue}")));\n`;
1096
- body += `${indent.get()}url = new_url;\n`;
1097
- return body;
1098
- },
1099
- });
1100
- body += `${indent.get()}url.query_pairs_mut().append_pair("${reqTokenValue}", &${reqTokenParam});\n`;
1101
- return body;
1102
- }
1103
- })}`;
1069
+ // passed to constructRequest. we only need to
1070
+ // clone it for the non-continuation case.
1071
+ let cloneUrl = false;
1072
+ if (method.strategy) {
1073
+ switch (method.strategy.kind) {
1074
+ case 'continuationToken': {
1075
+ const reqTokenParam = method.strategy.requestToken.name;
1076
+ body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(move |${reqTokenParam}: PagerState<String>| {\n`;
1077
+ body += `${indent.push().get()}let ${method.strategy.requestToken.kind === 'queryScalar' ? 'mut ' : ''}url = first_url.clone();\n`;
1078
+ if (method.strategy.requestToken.kind === 'queryScalar') {
1079
+ // if the url already contains the token query param,
1080
+ // e.g. we started on some page, then we need to remove
1081
+ // it before appending the token for the next page.
1082
+ const reqTokenValue = method.strategy.requestToken.key;
1083
+ body += `${indent.get()}${helpers.buildIfBlock(indent, {
1084
+ condition: `let PagerState::More(${reqTokenParam}) = ${reqTokenParam}`,
1085
+ body: (indent) => {
1086
+ let body = indent.get() + helpers.buildIfBlock(indent, {
1087
+ condition: `url.query_pairs().any(|(name, _)| name.eq("${reqTokenValue}"))`,
1088
+ body: (indent) => {
1089
+ let body = `${indent.get()}let mut new_url = url.clone();\n`;
1090
+ body += `${indent.get()}new_url.query_pairs_mut().clear().extend_pairs(url.query_pairs().filter(|(name, _)| name.ne("${reqTokenValue}")));\n`;
1091
+ body += `${indent.get()}url = new_url;\n`;
1092
+ return body;
1093
+ },
1094
+ }) + '\n';
1095
+ body += `${indent.get()}url.query_pairs_mut().append_pair("${reqTokenValue}", &${reqTokenParam});\n`;
1096
+ return body;
1097
+ }
1098
+ })}\n`;
1099
+ }
1100
+ break;
1104
1101
  }
1105
- break;
1106
- }
1107
- case 'nextLink': {
1108
- const nextLinkName = method.strategy.nextLink.name;
1109
- body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(move |${nextLinkName}: PagerState<Url>| {\n`;
1110
- body += `${indent.push().get()}let url = ` + helpers.buildMatch(indent, nextLinkName, [{
1111
- pattern: `PagerState::More(${nextLinkName})`,
1112
- body: (indent) => {
1113
- if (paramGroups.apiVersion && paramGroups.apiVersion.kind === 'queryScalar') {
1114
- const apiVersionKey = `"${paramGroups.apiVersion.key}"`;
1115
- // there are no APIs to set/update an existing query parameter.
1116
- // so, we filter the existing query params to remove the api-version
1117
- // query param. we then add back the filtered set and then add the
1118
- // api-version as specified on the client.
1119
- let setApiVerBody = `${indent.get()}let qp = ${nextLinkName}.query_pairs().filter(|(name, _)| name.ne(${apiVersionKey}));\n`;
1120
- setApiVerBody += `${indent.get()}let mut ${nextLinkName} = ${nextLinkName}.clone();\n`;
1121
- setApiVerBody += `${indent.get()}${nextLinkName}.query_pairs_mut().clear().extend_pairs(qp).append_pair(${apiVersionKey}, &${paramGroups.apiVersion.name});\n`;
1122
- setApiVerBody += `${indent.get()}${nextLinkName}\n`;
1123
- return setApiVerBody;
1102
+ case 'nextLink': {
1103
+ const nextLinkName = method.strategy.nextLinkPath[method.strategy.nextLinkPath.length - 1].name;
1104
+ body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(move |${nextLinkName}: PagerState<Url>| {\n`;
1105
+ body += `${indent.push().get()}let url = ` + helpers.buildMatch(indent, nextLinkName, [{
1106
+ pattern: `PagerState::More(${nextLinkName})`,
1107
+ body: (indent) => {
1108
+ if (paramGroups.apiVersion && paramGroups.apiVersion.kind === 'queryScalar') {
1109
+ const apiVersionKey = `"${paramGroups.apiVersion.key}"`;
1110
+ // there are no APIs to set/update an existing query parameter.
1111
+ // so, we filter the existing query params to remove the api-version
1112
+ // query param. we then add back the filtered set and then add the
1113
+ // api-version as specified on the client.
1114
+ let setApiVerBody = `${indent.get()}let qp = ${nextLinkName}.query_pairs().filter(|(name, _)| name.ne(${apiVersionKey}));\n`;
1115
+ setApiVerBody += `${indent.get()}let mut ${nextLinkName} = ${nextLinkName}.clone();\n`;
1116
+ setApiVerBody += `${indent.get()}${nextLinkName}.query_pairs_mut().clear().extend_pairs(qp).append_pair(${apiVersionKey}, &${paramGroups.apiVersion.name});\n`;
1117
+ setApiVerBody += `${indent.get()}${nextLinkName}\n`;
1118
+ return setApiVerBody;
1119
+ }
1120
+ return `${indent.get()} ${nextLinkName}\n`;
1124
1121
  }
1125
- return `${indent.get()} ${nextLinkName}\n`;
1126
- }
1127
- }, {
1128
- pattern: 'PagerState::Initial',
1129
- body: (indent) => `${indent.get()}${urlVar}.clone()\n`
1130
- }]);
1131
- body += ';\n';
1132
- break;
1122
+ }, {
1123
+ pattern: 'PagerState::Initial',
1124
+ body: (indent) => `${indent.get()}${urlVar}.clone()\n`
1125
+ }]);
1126
+ body += ';\n';
1127
+ break;
1128
+ }
1133
1129
  }
1134
1130
  }
1135
- let rspType;
1136
- let rspInto;
1137
- if (method.strategy.kind === 'continuationToken' && method.strategy.responseToken.kind === 'responseHeaderScalar') {
1131
+ else {
1132
+ // no next link when there's no strategy
1133
+ body += `${indent.get()}Ok(Pager::from_callback(move |_: PagerState<Url>| {\n`;
1134
+ cloneUrl = true;
1135
+ }
1136
+ // Pipeline::send() returns a BufResponse, so no reason to declare the type if not something else.
1137
+ let rspType = '';
1138
+ let rspInto = '';
1139
+ if (method.strategy && method.strategy.kind === 'continuationToken' && method.strategy.responseToken.kind === 'responseHeaderScalar') {
1138
1140
  // the continuation token comes from a response header. therefore,
1139
1141
  // we need a Response<T> so we have access to the header trait.
1140
1142
  use.addForType(method.returns.type.type);
1141
- rspType = helpers.getTypeDeclaration(method.returns.type.type);
1143
+ const rspTypeDecl = helpers.getTypeDeclaration(method.returns.type.type);
1144
+ rspType = `: ${rspTypeDecl}`;
1142
1145
  rspInto = '.into()';
1143
1146
  }
1144
- else {
1145
- // continuation token comes from the response body.
1146
- // we'll deconstruct the raw response and parse it later.
1147
- use.add('azure_core', 'http::RawResponse');
1148
- rspType = 'RawResponse';
1149
- rspInto = '';
1150
- }
1151
- body += constructRequest(indent, use, method, paramGroups, true);
1147
+ body += constructRequest(indent, use, method, paramGroups, true, cloneUrl);
1152
1148
  body += `${indent.get()}let ctx = options.method_options.context.clone();\n`;
1153
1149
  body += `${indent.get()}let pipeline = pipeline.clone();\n`;
1154
1150
  body += `${indent.get()}async move {\n`;
1155
- body += `${indent.push().get()}let rsp: ${rspType} = pipeline.send(&ctx, &mut request).await?${rspInto};\n`;
1156
- if (rspType === 'RawResponse') {
1157
- body += errIfNotSuccessResponse(use, indent);
1158
- }
1151
+ body += `${indent.push().get()}let rsp${rspType} = pipeline.send(&ctx, &mut request, ${getPipelineSendOptions(indent, use, method)}).await?${rspInto};\n`;
1159
1152
  // check if we need to extract the next link field from the response model
1160
- if (method.strategy.kind === 'nextLink' || method.strategy.responseToken.kind === 'modelField') {
1161
- use.add('azure_core', 'http::RawResponse');
1153
+ if (method.strategy && (method.strategy.kind === 'nextLink' || method.strategy.responseToken.kind === 'nextLink')) {
1154
+ const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
1155
+ use.add('azure_core', bodyFormat, 'http::BufResponse');
1162
1156
  body += `${indent.get()}let (status, headers, body) = rsp.deconstruct();\n`;
1163
1157
  body += `${indent.get()}let bytes = body.collect().await?;\n`;
1164
1158
  const deserialize = bodyFormat === 'json' ? 'json::from_json' : 'xml::read_xml';
1165
1159
  body += `${indent.get()}let res: ${helpers.getTypeDeclaration(helpers.unwrapType(method.returns.type))} = ${deserialize}(&bytes)?;\n`;
1166
- body += `${indent.get()}let rsp = RawResponse::from_bytes(status, headers, bytes).into();\n`;
1160
+ body += `${indent.get()}let rsp = BufResponse::from_bytes(status, headers, bytes).into();\n`;
1167
1161
  }
1168
- let srcNextPage;
1169
- let nextPageValue;
1170
- let continuation;
1171
- switch (method.strategy.kind) {
1172
- case 'continuationToken':
1173
- nextPageValue = method.strategy.responseToken.name;
1174
- continuation = nextPageValue;
1175
- switch (method.strategy.responseToken.kind) {
1176
- case 'modelField':
1177
- srcNextPage = `res.${nextPageValue}`;
1178
- break;
1179
- case 'responseHeaderScalar':
1180
- if (!method.responseHeaders) {
1181
- throw new CodegenError('InternalError', `missing response headers trait for method ${method.name}`);
1182
- }
1183
- use.addForType(method.responseHeaders);
1184
- srcNextPage = `rsp.${method.strategy.responseToken.name}()?`;
1185
- break;
1162
+ if (method.strategy) {
1163
+ /** provides access to the next link field, handling nested fields as required */
1164
+ const buildNextLinkPath = function (nextLinkPath) {
1165
+ let fullPath = nextLinkPath[0].name;
1166
+ if (nextLinkPath.length > 1) {
1167
+ for (let i = 1; i < nextLinkPath.length; ++i) {
1168
+ const prev = nextLinkPath[i - 1];
1169
+ const cur = nextLinkPath[i];
1170
+ fullPath += `.and_then(|${prev.name}| ${prev.name}.${cur.name})`;
1171
+ }
1186
1172
  }
1187
- break;
1188
- case 'nextLink':
1189
- nextPageValue = method.strategy.nextLink.name;
1190
- srcNextPage = `res.${nextPageValue}`;
1191
- continuation = `${nextPageValue}.parse()?`;
1192
- break;
1173
+ return fullPath;
1174
+ };
1175
+ let srcNextPage;
1176
+ let nextPageValue;
1177
+ let continuation;
1178
+ switch (method.strategy.kind) {
1179
+ case 'continuationToken':
1180
+ switch (method.strategy.responseToken.kind) {
1181
+ case 'nextLink':
1182
+ nextPageValue = method.strategy.responseToken.nextLinkPath[method.strategy.responseToken.nextLinkPath.length - 1].name;
1183
+ srcNextPage = `res.${buildNextLinkPath(method.strategy.responseToken.nextLinkPath)}`;
1184
+ break;
1185
+ case 'responseHeaderScalar':
1186
+ if (!method.responseHeaders) {
1187
+ throw new CodegenError('InternalError', `missing response headers trait for method ${method.name}`);
1188
+ }
1189
+ nextPageValue = method.strategy.responseToken.name;
1190
+ use.addForType(method.responseHeaders);
1191
+ srcNextPage = `rsp.${method.strategy.responseToken.name}()?`;
1192
+ break;
1193
+ }
1194
+ continuation = nextPageValue;
1195
+ break;
1196
+ case 'nextLink': {
1197
+ const lastFieldName = method.strategy.nextLinkPath[method.strategy.nextLinkPath.length - 1].name;
1198
+ nextPageValue = lastFieldName;
1199
+ srcNextPage = `res.${buildNextLinkPath(method.strategy.nextLinkPath)}`;
1200
+ continuation = `${lastFieldName}.parse()?`;
1201
+ break;
1202
+ }
1203
+ }
1204
+ // we need to handle the case where the next page value is the empty string,
1205
+ // so checking strictly for None(theNextLink) is insufficient.
1206
+ // the most common case for this is XML, e.g. an empty tag like <NextLink />
1207
+ body += `${indent.get()}Ok(${helpers.buildMatch(indent, srcNextPage, [{
1208
+ pattern: `Some(${nextPageValue}) if !${nextPageValue}.is_empty()`,
1209
+ body: (indent) => {
1210
+ return `${indent.get()}response: rsp, continuation: ${continuation}\n`;
1211
+ },
1212
+ returns: 'PagerResult::More',
1213
+ }, {
1214
+ pattern: '_',
1215
+ body: (indent) => {
1216
+ return `${indent.get()}response: rsp\n`;
1217
+ },
1218
+ returns: 'PagerResult::Done',
1219
+ }])}`;
1220
+ body += ')\n'; // end Ok
1221
+ }
1222
+ else {
1223
+ // non-continuation case, so we don't need to worry about next links, continuation tokens, etc...
1224
+ body += `${indent.get()}Ok(PagerResult::Done { response: rsp.into() })\n`;
1193
1225
  }
1194
- // we need to handle the case where the next page value is the empty string,
1195
- // so checking strictly for None(theNextLink) is insufficient.
1196
- // the most common case for this is XML, e.g. an empty tag like <NextLink />
1197
- body += `${indent.get()}Ok(${helpers.buildMatch(indent, srcNextPage, [{
1198
- pattern: `Some(${nextPageValue}) if !${nextPageValue}.is_empty()`,
1199
- body: (indent) => {
1200
- return `${indent.get()}response: rsp, continuation: ${continuation}`;
1201
- },
1202
- returns: 'PagerResult::More',
1203
- }, {
1204
- pattern: '_',
1205
- body: (indent) => {
1206
- return `${indent.get()}response: rsp`;
1207
- },
1208
- returns: 'PagerResult::Done',
1209
- }])}`;
1210
- body += ')\n'; // end Ok
1211
1226
  body += `${indent.pop().get()}}\n`; // end async move
1212
1227
  body += `${indent.pop().get()}}))`; // end Ok/Pager::from_callback
1213
1228
  return body;
@@ -1223,7 +1238,7 @@ function getPageableMethodBody(indent, use, client, method) {
1223
1238
  */
1224
1239
  function getLroMethodBody(indent, use, client, method) {
1225
1240
  const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
1226
- use.add('azure_core::http', 'Method', 'RawResponse', 'Request', 'Url');
1241
+ use.add('azure_core::http', 'Method', 'BufResponse', 'Request', 'Url');
1227
1242
  use.add('azure_core::http::headers', 'RETRY_AFTER', 'X_MS_RETRY_AFTER_MS', 'RETRY_AFTER_MS');
1228
1243
  use.add('azure_core::http::poller', 'get_retry_after', 'PollerResult', 'PollerState', 'PollerStatus', 'StatusMonitor as _');
1229
1244
  use.addForType(method.returns.type);
@@ -1233,40 +1248,39 @@ function getLroMethodBody(indent, use, client, method) {
1233
1248
  let body = 'let options = options.unwrap_or_default().into_owned();\n';
1234
1249
  body += `${indent.get()}let pipeline = self.pipeline.clone();\n`;
1235
1250
  body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}${urlVar} = self.${getEndpointFieldName(client)}.clone();\n`;
1236
- body += `${constructUrl(indent, use, method, paramGroups, urlVar)}\n\n`;
1251
+ body += constructUrl(indent, use, method, paramGroups, urlVar);
1237
1252
  if (paramGroups.apiVersion) {
1238
- body += `${indent.get()}let ${paramGroups.apiVersion.name} = ${getHeaderPathQueryParamValue(use, paramGroups.apiVersion, true)}.clone();\n\n`;
1253
+ body += `${indent.get()}let ${paramGroups.apiVersion.name} = ${getHeaderPathQueryParamValue(use, paramGroups.apiVersion, true)}.clone();\n`;
1239
1254
  }
1240
1255
  body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(\n`;
1241
1256
  body += `${indent.push().get()}move |next_link: PollerState<Url>| {\n`;
1242
1257
  body += `${indent.push().get()}let (mut request, next_link) = ${helpers.buildMatch(indent, 'next_link', [{
1243
1258
  pattern: `PollerState::More(next_link)`,
1244
1259
  body: (indent) => {
1260
+ var _a;
1245
1261
  let body = '';
1246
- if (paramGroups.apiVersion) {
1247
- body += `${indent.get()}let qp = next_link.query_pairs().filter(|(name, _)| name.ne("api-version"));\n`;
1262
+ if (((_a = paramGroups.apiVersion) === null || _a === void 0 ? void 0 : _a.kind) === 'queryScalar') {
1263
+ body += `${indent.get()}let qp = next_link.query_pairs().filter(|(name, _)| name.ne("${paramGroups.apiVersion.key}"));\n`;
1264
+ body += `${indent.get()}let mut next_link = next_link.clone();\n`;
1265
+ body += `${indent.get()}next_link.query_pairs_mut().clear().extend_pairs(qp).append_pair("${paramGroups.apiVersion.key}", &${paramGroups.apiVersion.name});\n`;
1248
1266
  }
1249
- body += `${indent.get()}let mut next_link = next_link.clone();\n`;
1250
- if (paramGroups.apiVersion) {
1251
- body += `${indent.get()}next_link.query_pairs_mut().clear().extend_pairs(qp).append_pair("api-version", &${paramGroups.apiVersion.name});\n\n`;
1252
- }
1253
- body += `${indent.get()}let ${paramGroups.header.length > 0 ? 'mut ' : ''}request = Request::new(next_link.clone(), Method::Get);`;
1254
- body += `\n${applyHeaderParams(indent, use, method, paramGroups, true)}\n\n`;
1267
+ body += `${indent.get()}let ${paramGroups.header.length > 0 ? 'mut ' : ''}request = Request::new(next_link.clone(), Method::Get);\n`;
1268
+ body += applyHeaderParams(indent, use, method, paramGroups, true);
1255
1269
  body += `${indent.get()}(request, next_link)\n`;
1256
1270
  return body;
1257
1271
  },
1258
1272
  }, {
1259
1273
  pattern: 'PollerState::Initial',
1260
1274
  body: (indent) => {
1261
- let body = `${constructRequest(indent, use, method, paramGroups, true, true, false)}\n`;
1275
+ let body = constructRequest(indent, use, method, paramGroups, true, true, false);
1262
1276
  body += `${indent.get()}(request, url.clone())\n`;
1263
1277
  return body;
1264
1278
  },
1265
- }])};\n\n`;
1279
+ }])};\n`;
1266
1280
  body += `${indent.get()}let ctx = options.method_options.context.clone();\n`;
1267
1281
  body += `${indent.get()}let pipeline = pipeline.clone();\n`;
1268
1282
  body += `${indent.get()}async move {\n`;
1269
- body += `${indent.push().get()}let rsp: RawResponse = pipeline.send(&ctx, &mut request).await?;\n`;
1283
+ body += `${indent.push().get()}let rsp = pipeline.send(&ctx, &mut request, ${getPipelineSendOptions(indent, use, method)}).await?;\n`;
1270
1284
  body += `${indent.get()}let (status, headers, body) = rsp.deconstruct();\n`;
1271
1285
  body += `${indent.get()}let retry_after = get_retry_after(&headers, &[X_MS_RETRY_AFTER_MS, RETRY_AFTER_MS, RETRY_AFTER], &options.poller_options);\n`;
1272
1286
  body += `${indent.get()}let bytes = body.collect().await?;\n`;
@@ -1279,7 +1293,7 @@ function getLroMethodBody(indent, use, client, method) {
1279
1293
  deserialize = 'xml::read_xml';
1280
1294
  }
1281
1295
  body += `${indent.get()}let res: ${helpers.getTypeDeclaration(helpers.unwrapType(method.returns.type))} = ${deserialize}(&bytes)?;\n`;
1282
- body += `${indent.get()}let rsp = RawResponse::from_bytes(status, headers, bytes).into();\n`;
1296
+ body += `${indent.get()}let rsp = BufResponse::from_bytes(status, headers, bytes).into();\n`;
1283
1297
  body += `${indent.get()}Ok(${helpers.buildMatch(indent, 'res.status()', [{
1284
1298
  pattern: `PollerStatus::InProgress`,
1285
1299
  body: (indent) => {
@@ -1305,7 +1319,7 @@ function getLroMethodBody(indent, use, client, method) {
1305
1319
  * @param param the param for which to get the value
1306
1320
  * @returns the code to use for the param's value
1307
1321
  */
1308
- function getClientEndpointParamValue(param) {
1322
+ function getClientSupplementalEndpointParamValue(param) {
1309
1323
  let paramName = param.name;
1310
1324
  if (param.optional) {
1311
1325
  paramName = 'options.' + paramName;
@@ -1449,9 +1463,20 @@ function nonCopyableType(type) {
1449
1463
  function isClientMethodOptions(type) {
1450
1464
  return type.kind === 'external' && type.name === 'ClientMethodOptions';
1451
1465
  }
1452
- /** returns true if the type is a credential */
1453
- function isCredential(type) {
1454
- const unwrappedType = helpers.unwrapType(type);
1455
- return unwrappedType.kind === 'tokenCredential';
1466
+ function getPipelineSendOptions(indent, use, method) {
1467
+ let options = '';
1468
+ if (method.statusCodes.length != 0) {
1469
+ use.add("azure_core::http", "PipelineSendOptions");
1470
+ use.add("azure_core::error", "CheckSuccessOptions");
1471
+ options += `Some(PipelineSendOptions {\n`;
1472
+ indent.push();
1473
+ options += `${indent.get()}check_success: CheckSuccessOptions{ success_codes: &[${method.statusCodes.join(', ')}]},\n`;
1474
+ options += `${indent.get()}..Default::default()\n`;
1475
+ options += `${indent.pop().get()}})`;
1476
+ return options;
1477
+ }
1478
+ else {
1479
+ return 'None';
1480
+ }
1456
1481
  }
1457
1482
  //# sourceMappingURL=clients.js.map