@azure-tools/typespec-rust 0.20.0 → 0.21.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.
- package/dist/src/codegen/cargotoml.d.ts.map +1 -1
- package/dist/src/codegen/cargotoml.js +3 -1
- package/dist/src/codegen/cargotoml.js.map +1 -1
- package/dist/src/codegen/clients.d.ts.map +1 -1
- package/dist/src/codegen/clients.js +246 -28
- package/dist/src/codegen/clients.js.map +1 -1
- package/dist/src/codegen/context.d.ts +10 -0
- package/dist/src/codegen/context.d.ts.map +1 -1
- package/dist/src/codegen/context.js +44 -2
- package/dist/src/codegen/context.js.map +1 -1
- package/dist/src/codegen/docTests.d.ts +12 -0
- package/dist/src/codegen/docTests.d.ts.map +1 -0
- package/dist/src/codegen/docTests.js +46 -0
- package/dist/src/codegen/docTests.js.map +1 -0
- package/dist/src/codegen/headerTraits.d.ts.map +1 -1
- package/dist/src/codegen/headerTraits.js +5 -0
- package/dist/src/codegen/headerTraits.js.map +1 -1
- package/dist/src/codegen/helpers.d.ts +38 -3
- package/dist/src/codegen/helpers.d.ts.map +1 -1
- package/dist/src/codegen/helpers.js +65 -4
- package/dist/src/codegen/helpers.js.map +1 -1
- package/dist/src/codegen/lib.d.ts.map +1 -1
- package/dist/src/codegen/lib.js +2 -0
- package/dist/src/codegen/lib.js.map +1 -1
- package/dist/src/codegen/models.d.ts.map +1 -1
- package/dist/src/codegen/models.js +172 -9
- package/dist/src/codegen/models.js.map +1 -1
- package/dist/src/codemodel/client.d.ts +14 -1
- package/dist/src/codemodel/client.d.ts.map +1 -1
- package/dist/src/codemodel/client.js +8 -0
- package/dist/src/codemodel/client.js.map +1 -1
- package/dist/src/codemodel/crate.js.map +1 -1
- package/dist/src/codemodel/types.d.ts +29 -7
- package/dist/src/codemodel/types.d.ts.map +1 -1
- package/dist/src/codemodel/types.js +13 -0
- package/dist/src/codemodel/types.js.map +1 -1
- package/dist/src/tcgcadapter/adapter.d.ts +5 -0
- package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
- package/dist/src/tcgcadapter/adapter.js +121 -34
- package/dist/src/tcgcadapter/adapter.js.map +1 -1
- package/package.json +28 -28
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cargotoml.d.ts","sourceRoot":"","sources":["../../../src/codegen/cargotoml.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"cargotoml.d.ts","sourceRoot":"","sources":["../../../src/codegen/cargotoml.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,MAAM,CAkBvD"}
|
|
@@ -14,7 +14,9 @@ export function emitCargoToml(crate) {
|
|
|
14
14
|
content += 'edition.workspace = true\n';
|
|
15
15
|
content += 'license.workspace = true\n';
|
|
16
16
|
content += 'repository.workspace = true\n';
|
|
17
|
-
content += 'rust-version.workspace = true\n';
|
|
17
|
+
content += 'rust-version.workspace = true\n\n';
|
|
18
|
+
content += '[features]\n';
|
|
19
|
+
content += 'default = ["azure_core/default"]\n';
|
|
18
20
|
if (crate.dependencies.length > 0) {
|
|
19
21
|
content += '\n[dependencies]\n';
|
|
20
22
|
for (const dependency of crate.dependencies) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cargotoml.js","sourceRoot":"","sources":["../../../src/codegen/cargotoml.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAI/F;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,OAAO,GAAG,sBAAsB,KAAK,CAAC,IAAI,iBAAiB,KAAK,CAAC,OAAO,KAAK,CAAC;IAClF,OAAO,IAAI,4BAA4B,CAAC;IACxC,OAAO,IAAI,4BAA4B,CAAC;IACxC,OAAO,IAAI,4BAA4B,CAAC;IACxC,OAAO,IAAI,+BAA+B,CAAC;IAC3C,OAAO,IAAI,
|
|
1
|
+
{"version":3,"file":"cargotoml.js","sourceRoot":"","sources":["../../../src/codegen/cargotoml.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAI/F;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,OAAO,GAAG,sBAAsB,KAAK,CAAC,IAAI,iBAAiB,KAAK,CAAC,OAAO,KAAK,CAAC;IAClF,OAAO,IAAI,4BAA4B,CAAC;IACxC,OAAO,IAAI,4BAA4B,CAAC;IACxC,OAAO,IAAI,4BAA4B,CAAC;IACxC,OAAO,IAAI,+BAA+B,CAAC;IAC3C,OAAO,IAAI,mCAAmC,CAAC;IAC/C,OAAO,IAAI,cAAc,CAAC;IAC1B,OAAO,IAAI,oCAAoC,CAAC;IAChD,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,oBAAoB,CAAC;QAChC,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAC5C,qEAAqE;YACrE,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACpI,OAAO,IAAI,GAAG,UAAU,CAAC,IAAI,wBAAwB,QAAQ,MAAM,CAAC;QACtE,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// cspell: ignore conv
|
|
6
6
|
import * as codegen from '@azure-tools/codegen';
|
|
7
7
|
import { values } from '@azure-tools/linq';
|
|
8
|
+
import { emitHeaderTraitDocExample } from './docTests.js';
|
|
8
9
|
import { CodegenError } from './errors.js';
|
|
9
10
|
import * as helpers from './helpers.js';
|
|
10
11
|
import queryString from 'query-string';
|
|
@@ -76,7 +77,7 @@ export function emitClients(crate) {
|
|
|
76
77
|
if (paramsDocs) {
|
|
77
78
|
body += paramsDocs;
|
|
78
79
|
}
|
|
79
|
-
body += `${indent.get()}#[tracing::new("${
|
|
80
|
+
body += `${indent.get()}#[tracing::new("${client.languageIndependentName}")]\n`;
|
|
80
81
|
body += `${indent.get()}pub fn ${constructor.name}(${getConstructorParamsSig(constructor.params, client.constructable.options, use)}) -> Result<Self> {\n`;
|
|
81
82
|
body += `${indent.get()}let options = options.unwrap_or_default();\n`;
|
|
82
83
|
// by convention, the endpoint param is always the first ctor param
|
|
@@ -142,7 +143,7 @@ export function emitClients(crate) {
|
|
|
142
143
|
body += `${indent.get()}option_env!("CARGO_PKG_VERSION"),\n`;
|
|
143
144
|
body += `${indent.get()}options.client_options,\n`;
|
|
144
145
|
body += `${indent.get()}Vec::default(),\n`;
|
|
145
|
-
body += `${indent.get()}${authPolicy ? 'vec![auth_policy]' : 'Vec::default()'},\n`;
|
|
146
|
+
body += `${indent.get()}${authPolicy ? 'vec![auth_policy]' : 'Vec::default()'}, None,\n`;
|
|
146
147
|
body += `${indent.pop().get()}),\n`; // end Pipeline::new
|
|
147
148
|
body += `${indent.pop().get()}})\n`; // end Ok
|
|
148
149
|
body += `${indent.pop().get()}}\n`; // end constructor
|
|
@@ -183,6 +184,12 @@ export function emitClients(crate) {
|
|
|
183
184
|
return getPageableMethodBody(indentation, use, client, method);
|
|
184
185
|
};
|
|
185
186
|
break;
|
|
187
|
+
case 'lro':
|
|
188
|
+
isPublicApi = true;
|
|
189
|
+
methodBody = (indentation) => {
|
|
190
|
+
return getLroMethodBody(indentation, use, client, method);
|
|
191
|
+
};
|
|
192
|
+
break;
|
|
186
193
|
case 'clientaccessor':
|
|
187
194
|
isSubclientNew = true;
|
|
188
195
|
methodBody = (indentation) => {
|
|
@@ -195,6 +202,10 @@ export function emitClients(crate) {
|
|
|
195
202
|
if (paramsDocs) {
|
|
196
203
|
body += paramsDocs;
|
|
197
204
|
}
|
|
205
|
+
// client accessors will never have response headers
|
|
206
|
+
if (method.kind !== 'clientaccessor' && method.responseHeaders) {
|
|
207
|
+
body += getHeaderTraitDocComment(indent, crate, method);
|
|
208
|
+
}
|
|
198
209
|
if (isPublicApi) {
|
|
199
210
|
body += `${indent.get()}#[tracing::function("${method.languageIndependentName}")]\n`;
|
|
200
211
|
}
|
|
@@ -275,7 +286,7 @@ function getMethodOptions(crate) {
|
|
|
275
286
|
}
|
|
276
287
|
}
|
|
277
288
|
body += '}\n\n'; // end options
|
|
278
|
-
if (method.kind === 'pageable') {
|
|
289
|
+
if (method.kind === 'pageable' || method.kind === 'lro') {
|
|
279
290
|
body += `impl ${helpers.getTypeDeclaration(method.options.type, true)} {\n`;
|
|
280
291
|
body += `${indent.get()}pub fn into_owned(self) -> ${method.options.type.name}<'static> {\n`;
|
|
281
292
|
body += `${indent.push().get()}${method.options.type.name} {\n`;
|
|
@@ -316,7 +327,7 @@ function getMethodOptions(crate) {
|
|
|
316
327
|
*/
|
|
317
328
|
function getParamsBlockDocComment(indent, callable) {
|
|
318
329
|
const formatParamBullet = function (paramName) {
|
|
319
|
-
return `*
|
|
330
|
+
return `* ${helpers.wrapInBackTicks(paramName)} - `;
|
|
320
331
|
};
|
|
321
332
|
let paramsContent = '';
|
|
322
333
|
for (const param of callable.params) {
|
|
@@ -412,6 +423,36 @@ function getMethodParamsSig(method, use) {
|
|
|
412
423
|
}
|
|
413
424
|
return paramsSig.join(', ');
|
|
414
425
|
}
|
|
426
|
+
/**
|
|
427
|
+
* returns documentation for header trait access if the method has response headers.
|
|
428
|
+
*
|
|
429
|
+
* @param indent the current indentation level
|
|
430
|
+
* @param crate the crate to which method belongs
|
|
431
|
+
* @param method the method for which to generate header trait documentation
|
|
432
|
+
* @returns the header trait documentation or empty string if not applicable
|
|
433
|
+
*/
|
|
434
|
+
function getHeaderTraitDocComment(indent, crate, method) {
|
|
435
|
+
if (!method.responseHeaders) {
|
|
436
|
+
return '';
|
|
437
|
+
}
|
|
438
|
+
const traitName = method.responseHeaders.name;
|
|
439
|
+
let headerDocs = `${indent.get()}///\n`;
|
|
440
|
+
headerDocs += `${indent.get()}/// ## Response Headers\n`;
|
|
441
|
+
headerDocs += `${indent.get()}///\n`;
|
|
442
|
+
headerDocs += `${indent.get()}/// The returned [${helpers.wrapInBackTicks('Response')}](azure_core::http::Response) implements the [${helpers.wrapInBackTicks(traitName)}] trait, which provides\n`;
|
|
443
|
+
headerDocs += `${indent.get()}/// access to response headers. For example:\n`;
|
|
444
|
+
headerDocs += `${indent.get()}///\n`;
|
|
445
|
+
headerDocs += emitHeaderTraitDocExample(crate.name, method.responseHeaders, indent);
|
|
446
|
+
headerDocs += `${indent.get()}///\n`;
|
|
447
|
+
headerDocs += `${indent.get()}/// ### Available headers\n`;
|
|
448
|
+
// List all available headers
|
|
449
|
+
for (const header of method.responseHeaders.headers) {
|
|
450
|
+
headerDocs += `${indent.get()}/// * [${helpers.wrapInBackTicks(header.name)}()](crate::generated::models::${traitName}::${header.name}) - ${header.header}\n`;
|
|
451
|
+
}
|
|
452
|
+
headerDocs += `${indent.get()}///\n`;
|
|
453
|
+
headerDocs += `${indent.get()}/// [${helpers.wrapInBackTicks(traitName)}]: crate::generated::models::${traitName}\n`;
|
|
454
|
+
return headerDocs;
|
|
455
|
+
}
|
|
415
456
|
/**
|
|
416
457
|
* returns the auth policy instantiation code if the ctor contains a credential param.
|
|
417
458
|
* the policy will be a local var named auth_policy.
|
|
@@ -593,7 +634,7 @@ function getMethodParamGroup(method) {
|
|
|
593
634
|
* @returns
|
|
594
635
|
*/
|
|
595
636
|
function getParamValueHelper(indent, param, inClosure, setter) {
|
|
596
|
-
if (param.optional) {
|
|
637
|
+
if (param.optional && param.type.kind !== 'literal') {
|
|
597
638
|
// optional params are in the unwrapped options local var
|
|
598
639
|
const op = indent.get() + helpers.buildIfBlock(indent, {
|
|
599
640
|
condition: `let Some(${param.name}) = ${inClosure ? '&' : ''}options.${param.name}`,
|
|
@@ -622,7 +663,10 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
622
663
|
}
|
|
623
664
|
/** returns & if the param needs to be borrowed (which is the majority of cases), else the empty string */
|
|
624
665
|
const borrowOrNot = function (param) {
|
|
625
|
-
|
|
666
|
+
// for string-based enums we call .as_ref() which elides the need to borrow.
|
|
667
|
+
// for numeric-based enums the borrow will be necessary.
|
|
668
|
+
// TODO: https://github.com/Azure/typespec-rust/issues/25
|
|
669
|
+
if (param.type.kind !== 'enum' && (param.type.kind !== 'ref' || param.type.type.kind === 'encodedBytes' || param.type.type.kind === 'slice')) {
|
|
626
670
|
return '&';
|
|
627
671
|
}
|
|
628
672
|
return '';
|
|
@@ -645,7 +689,7 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
645
689
|
body += `${indent.get()}let mut path = String::from(${path});\n`;
|
|
646
690
|
for (const pathParam of paramGroups.path) {
|
|
647
691
|
let wrapSortedVec = (s) => s;
|
|
648
|
-
let paramExpression =
|
|
692
|
+
let paramExpression = getHeaderPathQueryParamValue(use, pathParam, true);
|
|
649
693
|
if (pathParam.kind === 'pathHashMap') {
|
|
650
694
|
wrapSortedVec = (s) => `${indent.get()}{`
|
|
651
695
|
+ `${indent.push().get()}let mut ${pathParam.name}_vec = ${pathParam.name}.iter().collect::<Vec<_>>();\n`
|
|
@@ -706,9 +750,22 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
706
750
|
case 'matrix':
|
|
707
751
|
paramExpression = `&format!(";${pathParam.name}={${paramExpression}}")`;
|
|
708
752
|
break;
|
|
753
|
+
default:
|
|
754
|
+
paramExpression = `${borrowOrNot(pathParam)}${paramExpression}`;
|
|
709
755
|
}
|
|
710
756
|
}
|
|
711
|
-
|
|
757
|
+
if (pathParam.optional) {
|
|
758
|
+
body += `${indent.get()}path = ${helpers.buildMatch(indent, `options.${pathParam.name}`, [{
|
|
759
|
+
pattern: `Some(${pathParam.name})`,
|
|
760
|
+
body: (indent) => wrapSortedVec(`${indent.get()}path.replace("{${pathParam.segment}}", ${paramExpression})\n`),
|
|
761
|
+
}, {
|
|
762
|
+
pattern: `None`,
|
|
763
|
+
body: (indent) => `${indent.get()}path.replace("{${pathParam.segment}}", "")\n`,
|
|
764
|
+
}])};\n`;
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
body += wrapSortedVec(`${indent.get()}path = path.replace("{${pathParam.segment}}", ${paramExpression});\n`);
|
|
768
|
+
}
|
|
712
769
|
}
|
|
713
770
|
path = '&path';
|
|
714
771
|
body += `${indent.get()}${urlVarName} = ${urlVarName}.join(${path})?;\n`;
|
|
@@ -774,27 +831,19 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
774
831
|
return body;
|
|
775
832
|
}
|
|
776
833
|
/**
|
|
777
|
-
* emits the code for
|
|
778
|
-
* assumes that there's a local var 'url' which is the Url.
|
|
779
|
-
* creates a mutable local 'request' which is the Request instance.
|
|
834
|
+
* emits the code for setting HTTP headers in a request.
|
|
780
835
|
*
|
|
781
836
|
* @param indent the indentation helper currently in scope
|
|
782
837
|
* @param use the use statement builder currently in scope
|
|
783
838
|
* @param method the method for which we're building the body
|
|
784
839
|
* @param paramGroups the param groups for the provided method
|
|
785
840
|
* @param inClosure indicates if the request is being constructed within a closure (e.g. pageable methods)
|
|
786
|
-
* @returns the
|
|
841
|
+
* @returns the code which sets HTTP headers for the request
|
|
787
842
|
*/
|
|
788
|
-
function
|
|
843
|
+
function applyHeaderParams(indent, use, method, paramGroups, inClosure) {
|
|
789
844
|
var _a, _b, _c;
|
|
790
|
-
let body =
|
|
791
|
-
let optionalContentTypeParam;
|
|
845
|
+
let body = '';
|
|
792
846
|
for (const headerParam of paramGroups.header) {
|
|
793
|
-
// if the content-type header is optional, we need to emit it inside the "if let Some(body)" clause below.
|
|
794
|
-
if (headerParam.kind === 'headerScalar' && headerParam.optional && headerParam.header.toLowerCase() === 'content-type') {
|
|
795
|
-
optionalContentTypeParam = headerParam;
|
|
796
|
-
continue;
|
|
797
|
-
}
|
|
798
847
|
if (method.kind === 'pageable' && ((_a = method.strategy) === null || _a === void 0 ? void 0 : _a.kind) === 'continuationToken' && ((_b = method.strategy) === null || _b === void 0 ? void 0 : _b.requestToken.kind) === 'headerScalar' && ((_c = method.strategy) === null || _c === void 0 ? void 0 : _c.requestToken) === headerParam) {
|
|
799
848
|
// we have some special handling for the header continuation token.
|
|
800
849
|
// if we have a token value, i.e. from the next page, then use that value.
|
|
@@ -818,6 +867,32 @@ function constructRequest(indent, use, method, paramGroups, inClosure) {
|
|
|
818
867
|
return `${indent.get()}request.insert_header("${headerParam.header.toLowerCase()}", ${borrow}${getHeaderPathQueryParamValue(use, headerParam, !inClosure)});\n`;
|
|
819
868
|
});
|
|
820
869
|
}
|
|
870
|
+
return body;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* emits the code for building the HTTP request.
|
|
874
|
+
* assumes that there's a local var 'url' which is the Url.
|
|
875
|
+
* creates a mutable local 'request' which is the Request instance.
|
|
876
|
+
*
|
|
877
|
+
* @param indent the indentation helper currently in scope
|
|
878
|
+
* @param use the use statement builder currently in scope
|
|
879
|
+
* @param method the method for which we're building the body
|
|
880
|
+
* @param paramGroups the param groups for the provided method
|
|
881
|
+
* @param inClosure indicates if the request is being constructed within a closure (e.g. pageable methods)
|
|
882
|
+
* @param cloneUrl indicates if url should be cloned when it is passed to initialize request
|
|
883
|
+
* @param forceMut indicates whether request should get declared as 'mut' regardless of whether there are any headers to set
|
|
884
|
+
* @returns the request construction code
|
|
885
|
+
*/
|
|
886
|
+
function constructRequest(indent, use, method, paramGroups, inClosure, cloneUrl = false, forceMut = true) {
|
|
887
|
+
let body = `${indent.get()}let ${(forceMut || paramGroups.header.length > 0) ? 'mut ' : ''}request = Request::new(url${cloneUrl ? '.clone()' : ''}, Method::${codegen.capitalize(method.httpMethod)});\n`;
|
|
888
|
+
body += applyHeaderParams(indent, use, method, paramGroups, inClosure);
|
|
889
|
+
let optionalContentTypeParam;
|
|
890
|
+
for (const headerParam of paramGroups.header) {
|
|
891
|
+
// 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') {
|
|
893
|
+
optionalContentTypeParam = headerParam;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
821
896
|
const bodyParam = paramGroups.body;
|
|
822
897
|
if (bodyParam) {
|
|
823
898
|
body += getParamValueHelper(indent, bodyParam, inClosure, () => {
|
|
@@ -867,12 +942,13 @@ function constructRequest(indent, use, method, paramGroups, inClosure) {
|
|
|
867
942
|
*/
|
|
868
943
|
function errIfNotSuccessResponse(use, indent) {
|
|
869
944
|
use.add('azure_core', 'Error', 'Result');
|
|
945
|
+
use.add('azure_core::http::headers', 'ERROR_CODE');
|
|
870
946
|
use.add('azure_core::error', 'ErrorKind', 'HttpError');
|
|
871
947
|
return helpers.buildIfBlock(indent, {
|
|
872
948
|
condition: '!rsp.status().is_success()',
|
|
873
949
|
body: (indent) => {
|
|
874
950
|
let body = `${indent.get()}let status = rsp.status();\n`;
|
|
875
|
-
body += `${indent.get()}let http_error = HttpError::new(rsp).await;\n`;
|
|
951
|
+
body += `${indent.get()}let http_error = HttpError::new(rsp, Some(ERROR_CODE)).await;\n`;
|
|
876
952
|
body += `${indent.get()}let error_kind = ErrorKind::http_response(status, http_error.error_code().map(std::borrow::ToOwned::to_owned));\n`;
|
|
877
953
|
body += `${indent.get()}return Err(Error::new(error_kind, http_error));\n`;
|
|
878
954
|
return body;
|
|
@@ -891,6 +967,58 @@ function urlVarNeedsMut(paramGroups, method) {
|
|
|
891
967
|
}
|
|
892
968
|
return '';
|
|
893
969
|
}
|
|
970
|
+
/**
|
|
971
|
+
* emits "if path_param is empty then error" checks for string method path parameters
|
|
972
|
+
*
|
|
973
|
+
* @param indent the indentation helper currently in scope
|
|
974
|
+
* @param params the path params to enumerate, can be empty
|
|
975
|
+
* @returns the empty path param checks or the empty string if there are no checks
|
|
976
|
+
*/
|
|
977
|
+
function checkEmptyRequiredPathParams(indent, params) {
|
|
978
|
+
let checks = '';
|
|
979
|
+
for (const param of params) {
|
|
980
|
+
if (param.optional || param.location === 'client') {
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
checks += emitEmptyPathParamCheck(indent, param);
|
|
984
|
+
}
|
|
985
|
+
return checks;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* emits the "if path_param is empty then error" check.
|
|
989
|
+
* this is only applicable when the path param's type can
|
|
990
|
+
* be empty (e.g. a string). for types that can't be empty
|
|
991
|
+
* the empty string is returned.
|
|
992
|
+
*
|
|
993
|
+
* @param indent the indentation helper currently in scope
|
|
994
|
+
* @param param the path param for which to emit the check
|
|
995
|
+
* @returns the check or the empty string
|
|
996
|
+
*/
|
|
997
|
+
function emitEmptyPathParamCheck(indent, param) {
|
|
998
|
+
let toString = '';
|
|
999
|
+
const paramType = param.type.kind === 'ref' ? param.type.type : param.type;
|
|
1000
|
+
switch (paramType.kind) {
|
|
1001
|
+
case 'String':
|
|
1002
|
+
case 'str':
|
|
1003
|
+
// need to check these for zero length
|
|
1004
|
+
break;
|
|
1005
|
+
case 'enum':
|
|
1006
|
+
if (!paramType.extensible) {
|
|
1007
|
+
// fixed enums will always have a value
|
|
1008
|
+
return '';
|
|
1009
|
+
}
|
|
1010
|
+
// need to get the underlying string value
|
|
1011
|
+
toString = '.as_ref()';
|
|
1012
|
+
break;
|
|
1013
|
+
default:
|
|
1014
|
+
// no length to check so bail
|
|
1015
|
+
return '';
|
|
1016
|
+
}
|
|
1017
|
+
return helpers.buildIfBlock(indent, {
|
|
1018
|
+
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"));`,
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
894
1022
|
/**
|
|
895
1023
|
* constructs the body for an async client method
|
|
896
1024
|
*
|
|
@@ -901,10 +1029,11 @@ function urlVarNeedsMut(paramGroups, method) {
|
|
|
901
1029
|
* @returns the contents of the method body
|
|
902
1030
|
*/
|
|
903
1031
|
function getAsyncMethodBody(indent, use, client, method) {
|
|
904
|
-
use.add('azure_core::http', '
|
|
1032
|
+
use.add('azure_core::http', 'Method', 'Request');
|
|
905
1033
|
const paramGroups = getMethodParamGroup(method);
|
|
906
|
-
let body =
|
|
907
|
-
body +=
|
|
1034
|
+
let body = checkEmptyRequiredPathParams(indent, paramGroups.path);
|
|
1035
|
+
body += 'let options = options.unwrap_or_default();\n';
|
|
1036
|
+
body += `${indent.get()}let ctx = options.method_options.context.to_borrowed();\n`;
|
|
908
1037
|
body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}url = self.${getEndpointFieldName(client)}.clone();\n`;
|
|
909
1038
|
body += constructUrl(indent, use, method, paramGroups);
|
|
910
1039
|
body += constructRequest(indent, use, method, paramGroups, false);
|
|
@@ -931,13 +1060,15 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
931
1060
|
throw new CodegenError('InternalError', 'paged method with no strategy NYI');
|
|
932
1061
|
}
|
|
933
1062
|
const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
|
|
934
|
-
use.add('azure_core::http', 'Method', '
|
|
1063
|
+
use.add('azure_core::http', 'Method', 'Request', 'Url');
|
|
1064
|
+
use.add('azure_core::http::pager', 'PagerResult', 'PagerState');
|
|
935
1065
|
use.add('azure_core', bodyFormat, 'Result');
|
|
936
1066
|
use.addForType(method.returns.type);
|
|
937
1067
|
use.addForType(helpers.unwrapType(method.returns.type));
|
|
938
1068
|
const paramGroups = getMethodParamGroup(method);
|
|
939
1069
|
const urlVar = 'first_url';
|
|
940
|
-
let body =
|
|
1070
|
+
let body = checkEmptyRequiredPathParams(indent, paramGroups.path);
|
|
1071
|
+
body += 'let options = options.unwrap_or_default().into_owned();\n';
|
|
941
1072
|
body += `${indent.get()}let pipeline = self.pipeline.clone();\n`;
|
|
942
1073
|
body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}${urlVar} = self.${getEndpointFieldName(client)}.clone();\n`;
|
|
943
1074
|
body += constructUrl(indent, use, method, paramGroups, urlVar);
|
|
@@ -1081,6 +1212,93 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
1081
1212
|
body += `${indent.pop().get()}}))`; // end Ok/Pager::from_callback
|
|
1082
1213
|
return body;
|
|
1083
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* constructs the body for an LRO client method
|
|
1217
|
+
*
|
|
1218
|
+
* @param indent the indentation helper currently in scope
|
|
1219
|
+
* @param use the use statement builder currently in scope
|
|
1220
|
+
* @param client the client to which the method belongs
|
|
1221
|
+
* @param method the method for the body to build
|
|
1222
|
+
* @returns the contents of the method body
|
|
1223
|
+
*/
|
|
1224
|
+
function getLroMethodBody(indent, use, client, method) {
|
|
1225
|
+
const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
|
|
1226
|
+
use.add('azure_core::http', 'Method', 'RawResponse', 'Request', 'Url');
|
|
1227
|
+
use.add('azure_core::http::headers', 'RETRY_AFTER', 'X_MS_RETRY_AFTER_MS', 'RETRY_AFTER_MS');
|
|
1228
|
+
use.add('azure_core::http::poller', 'get_retry_after', 'PollerResult', 'PollerState', 'PollerStatus', 'StatusMonitor as _');
|
|
1229
|
+
use.addForType(method.returns.type);
|
|
1230
|
+
use.addForType(helpers.unwrapType(method.returns.type));
|
|
1231
|
+
const paramGroups = getMethodParamGroup(method);
|
|
1232
|
+
const urlVar = 'url';
|
|
1233
|
+
let body = 'let options = options.unwrap_or_default().into_owned();\n';
|
|
1234
|
+
body += `${indent.get()}let pipeline = self.pipeline.clone();\n`;
|
|
1235
|
+
body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}${urlVar} = self.${getEndpointFieldName(client)}.clone();\n`;
|
|
1236
|
+
body += `${constructUrl(indent, use, method, paramGroups, urlVar)}\n\n`;
|
|
1237
|
+
if (paramGroups.apiVersion) {
|
|
1238
|
+
body += `${indent.get()}let ${paramGroups.apiVersion.name} = ${getHeaderPathQueryParamValue(use, paramGroups.apiVersion, true)}.clone();\n\n`;
|
|
1239
|
+
}
|
|
1240
|
+
body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(\n`;
|
|
1241
|
+
body += `${indent.push().get()}move |next_link: PollerState<Url>| {\n`;
|
|
1242
|
+
body += `${indent.push().get()}let (mut request, next_link) = ${helpers.buildMatch(indent, 'next_link', [{
|
|
1243
|
+
pattern: `PollerState::More(next_link)`,
|
|
1244
|
+
body: (indent) => {
|
|
1245
|
+
let body = '';
|
|
1246
|
+
if (paramGroups.apiVersion) {
|
|
1247
|
+
body += `${indent.get()}let qp = next_link.query_pairs().filter(|(name, _)| name.ne("api-version"));\n`;
|
|
1248
|
+
}
|
|
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`;
|
|
1255
|
+
body += `${indent.get()}(request, next_link)\n`;
|
|
1256
|
+
return body;
|
|
1257
|
+
},
|
|
1258
|
+
}, {
|
|
1259
|
+
pattern: 'PollerState::Initial',
|
|
1260
|
+
body: (indent) => {
|
|
1261
|
+
let body = `${constructRequest(indent, use, method, paramGroups, true, true, false)}\n`;
|
|
1262
|
+
body += `${indent.get()}(request, url.clone())\n`;
|
|
1263
|
+
return body;
|
|
1264
|
+
},
|
|
1265
|
+
}])};\n\n`;
|
|
1266
|
+
body += `${indent.get()}let ctx = options.method_options.context.clone();\n`;
|
|
1267
|
+
body += `${indent.get()}let pipeline = pipeline.clone();\n`;
|
|
1268
|
+
body += `${indent.get()}async move {\n`;
|
|
1269
|
+
body += `${indent.push().get()}let rsp: RawResponse = pipeline.send(&ctx, &mut request).await?;\n`;
|
|
1270
|
+
body += `${indent.get()}let (status, headers, body) = rsp.deconstruct();\n`;
|
|
1271
|
+
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
|
+
body += `${indent.get()}let bytes = body.collect().await?;\n`;
|
|
1273
|
+
let deserialize = '';
|
|
1274
|
+
if (bodyFormat === 'json') {
|
|
1275
|
+
use.add('azure_core', 'json');
|
|
1276
|
+
deserialize = 'json::from_json';
|
|
1277
|
+
}
|
|
1278
|
+
else {
|
|
1279
|
+
deserialize = 'xml::read_xml';
|
|
1280
|
+
}
|
|
1281
|
+
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`;
|
|
1283
|
+
body += `${indent.get()}Ok(${helpers.buildMatch(indent, 'res.status()', [{
|
|
1284
|
+
pattern: `PollerStatus::InProgress`,
|
|
1285
|
+
body: (indent) => {
|
|
1286
|
+
return `${indent.get()}response: rsp, retry_after, next: next_link\n`;
|
|
1287
|
+
},
|
|
1288
|
+
returns: 'PollerResult::InProgress'
|
|
1289
|
+
}, {
|
|
1290
|
+
pattern: '_',
|
|
1291
|
+
body: (indent) => {
|
|
1292
|
+
return `${indent.get()}response: rsp`;
|
|
1293
|
+
},
|
|
1294
|
+
returns: 'PollerResult::Done'
|
|
1295
|
+
}])})\n`;
|
|
1296
|
+
body += `${indent.pop().get()}}\n`; // end async move
|
|
1297
|
+
body += `${indent.pop().get()}},\n`; // end move
|
|
1298
|
+
body += `${indent.get()}None,\n`;
|
|
1299
|
+
body += `${indent.pop().get()}))`; // end Ok/Poller::from_callback
|
|
1300
|
+
return body;
|
|
1301
|
+
}
|
|
1084
1302
|
/**
|
|
1085
1303
|
* contains the code to use when populating a client endpoint parameter value
|
|
1086
1304
|
* from a parameter of that type.
|
|
@@ -1179,8 +1397,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf) {
|
|
|
1179
1397
|
return encodeBytes(paramType, paramName);
|
|
1180
1398
|
case 'enum':
|
|
1181
1399
|
case 'scalar':
|
|
1182
|
-
if (paramType.kind === 'enum' && param.kind === 'queryScalar') {
|
|
1183
|
-
// append_pair
|
|
1400
|
+
if (paramType.kind === 'enum' && (param.kind === 'pathScalar' || param.kind === 'queryScalar')) {
|
|
1401
|
+
// append_pair and path.replace() want a reference to the string
|
|
1184
1402
|
// TODO: https://github.com/Azure/typespec-rust/issues/25
|
|
1185
1403
|
return `${paramName}.as_ref()`;
|
|
1186
1404
|
}
|