@azure-tools/typespec-rust 0.20.0 → 0.22.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 +272 -69
- 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 +66 -5
- 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 +38 -5
- package/dist/src/codemodel/client.d.ts.map +1 -1
- package/dist/src/codemodel/client.js +21 -1
- 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 +33 -11
- package/dist/src/codemodel/types.d.ts.map +1 -1
- package/dist/src/codemodel/types.js +16 -3
- package/dist/src/codemodel/types.js.map +1 -1
- package/dist/src/emitter.d.ts.map +1 -1
- package/dist/src/emitter.js +7 -1
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/tcgcadapter/adapter.d.ts +11 -0
- package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
- package/dist/src/tcgcadapter/adapter.js +156 -44
- package/dist/src/tcgcadapter/adapter.js.map +1 -1
- package/dist/src/tcgcadapter/helpers.js +1 -1
- package/dist/src/tcgcadapter/helpers.js.map +1 -1
- package/package.json +29 -29
|
@@ -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,CAuQxE"}
|
|
@@ -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,23 +77,22 @@ 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
|
|
83
84
|
const endpointParamName = constructor.params[0].name;
|
|
84
|
-
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`;
|
|
85
86
|
body += `${indent.get()}${helpers.buildIfBlock(indent, {
|
|
86
87
|
condition: `!${endpointParamName}.scheme().starts_with("http")`,
|
|
87
88
|
body: (indent) => `${indent.get()}return Err(azure_core::Error::message(azure_core::error::ErrorKind::Other, format!("{${endpointParamName}} must use http(s)")));\n`,
|
|
88
89
|
})}`;
|
|
89
|
-
body += `${indent.get()}${endpointParamName}.set_query(None);\n`;
|
|
90
90
|
// construct the supplemental path and join it to the endpoint
|
|
91
91
|
if (client.constructable.endpoint) {
|
|
92
92
|
const supplementalEndpoint = client.constructable.endpoint;
|
|
93
93
|
body += `${indent.get()}let mut host = String::from("${supplementalEndpoint.path}");\n`;
|
|
94
94
|
for (const param of supplementalEndpoint.parameters) {
|
|
95
|
-
body += `${indent.get()}host = host.replace("{${param.segment}}", ${
|
|
95
|
+
body += `${indent.get()}host = host.replace("{${param.segment}}", ${getClientSupplementalEndpointParamValue(param)});\n`;
|
|
96
96
|
}
|
|
97
97
|
body += `${indent.push().get()}${endpointParamName} = ${endpointParamName}.join(&host)?;\n`;
|
|
98
98
|
}
|
|
@@ -108,15 +108,11 @@ export function emitClients(crate) {
|
|
|
108
108
|
// exclude endpoint params as they aren't propagated to clients (they're consumed when creating the complete endpoint)
|
|
109
109
|
const sortedParams = values([...constructor.params]
|
|
110
110
|
.sort((a, b) => { return helpers.sortAscending(a.name, b.name); }))
|
|
111
|
-
.where((each) => each.kind !== '
|
|
111
|
+
.where((each) => each.kind !== 'clientSupplementalEndpoint' && each.kind !== 'clientCredential').toArray();
|
|
112
112
|
for (const param of sortedParams) {
|
|
113
113
|
if (param.optional) {
|
|
114
114
|
continue;
|
|
115
115
|
}
|
|
116
|
-
else if (isCredential(param.type)) {
|
|
117
|
-
// credential params aren't persisted on the client so skip them
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
116
|
if (!client.fields.find((v) => { return v.name === param.name; })) {
|
|
121
117
|
throw new CodegenError('InternalError', `didn't find field in client ${client.name} for param ${param.name}`);
|
|
122
118
|
}
|
|
@@ -142,7 +138,7 @@ export function emitClients(crate) {
|
|
|
142
138
|
body += `${indent.get()}option_env!("CARGO_PKG_VERSION"),\n`;
|
|
143
139
|
body += `${indent.get()}options.client_options,\n`;
|
|
144
140
|
body += `${indent.get()}Vec::default(),\n`;
|
|
145
|
-
body += `${indent.get()}${authPolicy ? 'vec![auth_policy]' : 'Vec::default()'},\n`;
|
|
141
|
+
body += `${indent.get()}${authPolicy ? 'vec![auth_policy]' : 'Vec::default()'}, None,\n`;
|
|
146
142
|
body += `${indent.pop().get()}),\n`; // end Pipeline::new
|
|
147
143
|
body += `${indent.pop().get()}})\n`; // end Ok
|
|
148
144
|
body += `${indent.pop().get()}}\n`; // end constructor
|
|
@@ -183,6 +179,12 @@ export function emitClients(crate) {
|
|
|
183
179
|
return getPageableMethodBody(indentation, use, client, method);
|
|
184
180
|
};
|
|
185
181
|
break;
|
|
182
|
+
case 'lro':
|
|
183
|
+
isPublicApi = true;
|
|
184
|
+
methodBody = (indentation) => {
|
|
185
|
+
return getLroMethodBody(indentation, use, client, method);
|
|
186
|
+
};
|
|
187
|
+
break;
|
|
186
188
|
case 'clientaccessor':
|
|
187
189
|
isSubclientNew = true;
|
|
188
190
|
methodBody = (indentation) => {
|
|
@@ -195,6 +197,10 @@ export function emitClients(crate) {
|
|
|
195
197
|
if (paramsDocs) {
|
|
196
198
|
body += paramsDocs;
|
|
197
199
|
}
|
|
200
|
+
// client accessors will never have response headers
|
|
201
|
+
if (method.kind !== 'clientaccessor' && method.responseHeaders) {
|
|
202
|
+
body += getHeaderTraitDocComment(indent, crate, method);
|
|
203
|
+
}
|
|
198
204
|
if (isPublicApi) {
|
|
199
205
|
body += `${indent.get()}#[tracing::function("${method.languageIndependentName}")]\n`;
|
|
200
206
|
}
|
|
@@ -275,7 +281,7 @@ function getMethodOptions(crate) {
|
|
|
275
281
|
}
|
|
276
282
|
}
|
|
277
283
|
body += '}\n\n'; // end options
|
|
278
|
-
if (method.kind === 'pageable') {
|
|
284
|
+
if (method.kind === 'pageable' || method.kind === 'lro') {
|
|
279
285
|
body += `impl ${helpers.getTypeDeclaration(method.options.type, true)} {\n`;
|
|
280
286
|
body += `${indent.get()}pub fn into_owned(self) -> ${method.options.type.name}<'static> {\n`;
|
|
281
287
|
body += `${indent.push().get()}${method.options.type.name} {\n`;
|
|
@@ -316,7 +322,7 @@ function getMethodOptions(crate) {
|
|
|
316
322
|
*/
|
|
317
323
|
function getParamsBlockDocComment(indent, callable) {
|
|
318
324
|
const formatParamBullet = function (paramName) {
|
|
319
|
-
return `*
|
|
325
|
+
return `* ${helpers.wrapInBackTicks(paramName)} - `;
|
|
320
326
|
};
|
|
321
327
|
let paramsContent = '';
|
|
322
328
|
for (const param of callable.params) {
|
|
@@ -412,6 +418,36 @@ function getMethodParamsSig(method, use) {
|
|
|
412
418
|
}
|
|
413
419
|
return paramsSig.join(', ');
|
|
414
420
|
}
|
|
421
|
+
/**
|
|
422
|
+
* returns documentation for header trait access if the method has response headers.
|
|
423
|
+
*
|
|
424
|
+
* @param indent the current indentation level
|
|
425
|
+
* @param crate the crate to which method belongs
|
|
426
|
+
* @param method the method for which to generate header trait documentation
|
|
427
|
+
* @returns the header trait documentation or empty string if not applicable
|
|
428
|
+
*/
|
|
429
|
+
function getHeaderTraitDocComment(indent, crate, method) {
|
|
430
|
+
if (!method.responseHeaders) {
|
|
431
|
+
return '';
|
|
432
|
+
}
|
|
433
|
+
const traitName = method.responseHeaders.name;
|
|
434
|
+
let headerDocs = `${indent.get()}///\n`;
|
|
435
|
+
headerDocs += `${indent.get()}/// ## Response Headers\n`;
|
|
436
|
+
headerDocs += `${indent.get()}///\n`;
|
|
437
|
+
headerDocs += `${indent.get()}/// The returned [${helpers.wrapInBackTicks('Response')}](azure_core::http::Response) implements the [${helpers.wrapInBackTicks(traitName)}] trait, which provides\n`;
|
|
438
|
+
headerDocs += `${indent.get()}/// access to response headers. For example:\n`;
|
|
439
|
+
headerDocs += `${indent.get()}///\n`;
|
|
440
|
+
headerDocs += emitHeaderTraitDocExample(crate.name, method.responseHeaders, indent);
|
|
441
|
+
headerDocs += `${indent.get()}///\n`;
|
|
442
|
+
headerDocs += `${indent.get()}/// ### Available headers\n`;
|
|
443
|
+
// List all available headers
|
|
444
|
+
for (const header of method.responseHeaders.headers) {
|
|
445
|
+
headerDocs += `${indent.get()}/// * [${helpers.wrapInBackTicks(header.name)}()](crate::generated::models::${traitName}::${header.name}) - ${header.header}\n`;
|
|
446
|
+
}
|
|
447
|
+
headerDocs += `${indent.get()}///\n`;
|
|
448
|
+
headerDocs += `${indent.get()}/// [${helpers.wrapInBackTicks(traitName)}]: crate::generated::models::${traitName}\n`;
|
|
449
|
+
return headerDocs;
|
|
450
|
+
}
|
|
415
451
|
/**
|
|
416
452
|
* returns the auth policy instantiation code if the ctor contains a credential param.
|
|
417
453
|
* the policy will be a local var named auth_policy.
|
|
@@ -593,7 +629,7 @@ function getMethodParamGroup(method) {
|
|
|
593
629
|
* @returns
|
|
594
630
|
*/
|
|
595
631
|
function getParamValueHelper(indent, param, inClosure, setter) {
|
|
596
|
-
if (param.optional) {
|
|
632
|
+
if (param.optional && param.type.kind !== 'literal') {
|
|
597
633
|
// optional params are in the unwrapped options local var
|
|
598
634
|
const op = indent.get() + helpers.buildIfBlock(indent, {
|
|
599
635
|
condition: `let Some(${param.name}) = ${inClosure ? '&' : ''}options.${param.name}`,
|
|
@@ -622,7 +658,10 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
622
658
|
}
|
|
623
659
|
/** returns & if the param needs to be borrowed (which is the majority of cases), else the empty string */
|
|
624
660
|
const borrowOrNot = function (param) {
|
|
625
|
-
|
|
661
|
+
// for string-based enums we call .as_ref() which elides the need to borrow.
|
|
662
|
+
// for numeric-based enums the borrow will be necessary.
|
|
663
|
+
// TODO: https://github.com/Azure/typespec-rust/issues/25
|
|
664
|
+
if (param.type.kind !== 'enum' && (param.type.kind !== 'ref' || param.type.type.kind === 'encodedBytes' || param.type.type.kind === 'slice')) {
|
|
626
665
|
return '&';
|
|
627
666
|
}
|
|
628
667
|
return '';
|
|
@@ -645,7 +684,7 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
645
684
|
body += `${indent.get()}let mut path = String::from(${path});\n`;
|
|
646
685
|
for (const pathParam of paramGroups.path) {
|
|
647
686
|
let wrapSortedVec = (s) => s;
|
|
648
|
-
let paramExpression =
|
|
687
|
+
let paramExpression = getHeaderPathQueryParamValue(use, pathParam, true);
|
|
649
688
|
if (pathParam.kind === 'pathHashMap') {
|
|
650
689
|
wrapSortedVec = (s) => `${indent.get()}{`
|
|
651
690
|
+ `${indent.push().get()}let mut ${pathParam.name}_vec = ${pathParam.name}.iter().collect::<Vec<_>>();\n`
|
|
@@ -706,9 +745,22 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
706
745
|
case 'matrix':
|
|
707
746
|
paramExpression = `&format!(";${pathParam.name}={${paramExpression}}")`;
|
|
708
747
|
break;
|
|
748
|
+
default:
|
|
749
|
+
paramExpression = `${borrowOrNot(pathParam)}${paramExpression}`;
|
|
709
750
|
}
|
|
710
751
|
}
|
|
711
|
-
|
|
752
|
+
if (pathParam.optional) {
|
|
753
|
+
body += `${indent.get()}path = ${helpers.buildMatch(indent, `options.${pathParam.name}`, [{
|
|
754
|
+
pattern: `Some(${pathParam.name})`,
|
|
755
|
+
body: (indent) => wrapSortedVec(`${indent.get()}path.replace("{${pathParam.segment}}", ${paramExpression})\n`),
|
|
756
|
+
}, {
|
|
757
|
+
pattern: `None`,
|
|
758
|
+
body: (indent) => `${indent.get()}path.replace("{${pathParam.segment}}", "")\n`,
|
|
759
|
+
}])};\n`;
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
762
|
+
body += wrapSortedVec(`${indent.get()}path = path.replace("{${pathParam.segment}}", ${paramExpression});\n`);
|
|
763
|
+
}
|
|
712
764
|
}
|
|
713
765
|
path = '&path';
|
|
714
766
|
body += `${indent.get()}${urlVarName} = ${urlVarName}.join(${path})?;\n`;
|
|
@@ -774,27 +826,19 @@ function constructUrl(indent, use, method, paramGroups, urlVarName = 'url') {
|
|
|
774
826
|
return body;
|
|
775
827
|
}
|
|
776
828
|
/**
|
|
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.
|
|
829
|
+
* emits the code for setting HTTP headers in a request.
|
|
780
830
|
*
|
|
781
831
|
* @param indent the indentation helper currently in scope
|
|
782
832
|
* @param use the use statement builder currently in scope
|
|
783
833
|
* @param method the method for which we're building the body
|
|
784
834
|
* @param paramGroups the param groups for the provided method
|
|
785
835
|
* @param inClosure indicates if the request is being constructed within a closure (e.g. pageable methods)
|
|
786
|
-
* @returns the
|
|
836
|
+
* @returns the code which sets HTTP headers for the request
|
|
787
837
|
*/
|
|
788
|
-
function
|
|
838
|
+
function applyHeaderParams(indent, use, method, paramGroups, inClosure) {
|
|
789
839
|
var _a, _b, _c;
|
|
790
|
-
let body =
|
|
791
|
-
let optionalContentTypeParam;
|
|
840
|
+
let body = '';
|
|
792
841
|
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
842
|
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
843
|
// we have some special handling for the header continuation token.
|
|
800
844
|
// if we have a token value, i.e. from the next page, then use that value.
|
|
@@ -805,6 +849,12 @@ function constructRequest(indent, use, method, paramGroups, inClosure) {
|
|
|
805
849
|
});
|
|
806
850
|
continue;
|
|
807
851
|
}
|
|
852
|
+
if (isOptionalContentTypeHeader(headerParam)) {
|
|
853
|
+
// when the body is optional, the Content-Type header
|
|
854
|
+
// will be set IFF the optional body param is not None.
|
|
855
|
+
// this logic happens elsewhere so we skip it here.
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
808
858
|
body += getParamValueHelper(indent, headerParam, inClosure, () => {
|
|
809
859
|
if (headerParam.kind === 'headerHashMap') {
|
|
810
860
|
let setter = `for (k, v) in &${headerParam.name} {\n`;
|
|
@@ -818,6 +868,36 @@ function constructRequest(indent, use, method, paramGroups, inClosure) {
|
|
|
818
868
|
return `${indent.get()}request.insert_header("${headerParam.header.toLowerCase()}", ${borrow}${getHeaderPathQueryParamValue(use, headerParam, !inClosure)});\n`;
|
|
819
869
|
});
|
|
820
870
|
}
|
|
871
|
+
return body;
|
|
872
|
+
}
|
|
873
|
+
/** type guard to determine if headerParam is an optional Content-Type header */
|
|
874
|
+
function isOptionalContentTypeHeader(headerParam) {
|
|
875
|
+
return headerParam.kind === 'headerScalar' && headerParam.optional && headerParam.header.toLowerCase() === 'content-type';
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* emits the code for building the HTTP request.
|
|
879
|
+
* assumes that there's a local var 'url' which is the Url.
|
|
880
|
+
* creates a mutable local 'request' which is the Request instance.
|
|
881
|
+
*
|
|
882
|
+
* @param indent the indentation helper currently in scope
|
|
883
|
+
* @param use the use statement builder currently in scope
|
|
884
|
+
* @param method the method for which we're building the body
|
|
885
|
+
* @param paramGroups the param groups for the provided method
|
|
886
|
+
* @param inClosure indicates if the request is being constructed within a closure (e.g. pageable methods)
|
|
887
|
+
* @param cloneUrl indicates if url should be cloned when it is passed to initialize request
|
|
888
|
+
* @param forceMut indicates whether request should get declared as 'mut' regardless of whether there are any headers to set
|
|
889
|
+
* @returns the request construction code
|
|
890
|
+
*/
|
|
891
|
+
function constructRequest(indent, use, method, paramGroups, inClosure, cloneUrl = false, forceMut = true) {
|
|
892
|
+
let body = `${indent.get()}let ${(forceMut || paramGroups.header.length > 0) ? 'mut ' : ''}request = Request::new(url${cloneUrl ? '.clone()' : ''}, Method::${codegen.capitalize(method.httpMethod)});\n`;
|
|
893
|
+
body += applyHeaderParams(indent, use, method, paramGroups, inClosure);
|
|
894
|
+
let optionalContentTypeParam;
|
|
895
|
+
for (const headerParam of paramGroups.header) {
|
|
896
|
+
// if the content-type header is optional, we need to emit it inside the "if let Some(body)" clause below.
|
|
897
|
+
if (isOptionalContentTypeHeader(headerParam)) {
|
|
898
|
+
optionalContentTypeParam = headerParam;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
821
901
|
const bodyParam = paramGroups.body;
|
|
822
902
|
if (bodyParam) {
|
|
823
903
|
body += getParamValueHelper(indent, bodyParam, inClosure, () => {
|
|
@@ -860,24 +940,15 @@ function constructRequest(indent, use, method, paramGroups, inClosure) {
|
|
|
860
940
|
return body;
|
|
861
941
|
}
|
|
862
942
|
/**
|
|
863
|
-
* Return an error if a local
|
|
943
|
+
* Return an error if a local BufResponse variable "rsp" has a non-success status code.
|
|
864
944
|
* @param use the use statement builder currently in scope
|
|
865
945
|
* @param indent the indentation helper currently in scope
|
|
866
946
|
* @returns code to return an error if the status code of "rsp" doesn't indicate success
|
|
867
947
|
*/
|
|
868
948
|
function errIfNotSuccessResponse(use, indent) {
|
|
869
|
-
use.add('azure_core', '
|
|
870
|
-
|
|
871
|
-
return
|
|
872
|
-
condition: '!rsp.status().is_success()',
|
|
873
|
-
body: (indent) => {
|
|
874
|
-
let body = `${indent.get()}let status = rsp.status();\n`;
|
|
875
|
-
body += `${indent.get()}let http_error = HttpError::new(rsp).await;\n`;
|
|
876
|
-
body += `${indent.get()}let error_kind = ErrorKind::http_response(status, http_error.error_code().map(std::borrow::ToOwned::to_owned));\n`;
|
|
877
|
-
body += `${indent.get()}return Err(Error::new(error_kind, http_error));\n`;
|
|
878
|
-
return body;
|
|
879
|
-
},
|
|
880
|
-
});
|
|
949
|
+
use.add('azure_core::http', 'check_success');
|
|
950
|
+
const body = `${indent.get()}let rsp = check_success(rsp).await?;\n`;
|
|
951
|
+
return body;
|
|
881
952
|
}
|
|
882
953
|
/**
|
|
883
954
|
* Returns 'mut ' if the Url local var needs to be mutable, else the empty string.
|
|
@@ -891,6 +962,58 @@ function urlVarNeedsMut(paramGroups, method) {
|
|
|
891
962
|
}
|
|
892
963
|
return '';
|
|
893
964
|
}
|
|
965
|
+
/**
|
|
966
|
+
* emits "if path_param is empty then error" checks for string method path parameters
|
|
967
|
+
*
|
|
968
|
+
* @param indent the indentation helper currently in scope
|
|
969
|
+
* @param params the path params to enumerate, can be empty
|
|
970
|
+
* @returns the empty path param checks or the empty string if there are no checks
|
|
971
|
+
*/
|
|
972
|
+
function checkEmptyRequiredPathParams(indent, params) {
|
|
973
|
+
let checks = '';
|
|
974
|
+
for (const param of params) {
|
|
975
|
+
if (param.optional || param.location === 'client') {
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
checks += emitEmptyPathParamCheck(indent, param);
|
|
979
|
+
}
|
|
980
|
+
return checks;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* emits the "if path_param is empty then error" check.
|
|
984
|
+
* this is only applicable when the path param's type can
|
|
985
|
+
* be empty (e.g. a string). for types that can't be empty
|
|
986
|
+
* the empty string is returned.
|
|
987
|
+
*
|
|
988
|
+
* @param indent the indentation helper currently in scope
|
|
989
|
+
* @param param the path param for which to emit the check
|
|
990
|
+
* @returns the check or the empty string
|
|
991
|
+
*/
|
|
992
|
+
function emitEmptyPathParamCheck(indent, param) {
|
|
993
|
+
let toString = '';
|
|
994
|
+
const paramType = param.type.kind === 'ref' ? param.type.type : param.type;
|
|
995
|
+
switch (paramType.kind) {
|
|
996
|
+
case 'String':
|
|
997
|
+
case 'str':
|
|
998
|
+
// need to check these for zero length
|
|
999
|
+
break;
|
|
1000
|
+
case 'enum':
|
|
1001
|
+
if (!paramType.extensible) {
|
|
1002
|
+
// fixed enums will always have a value
|
|
1003
|
+
return '';
|
|
1004
|
+
}
|
|
1005
|
+
// need to get the underlying string value
|
|
1006
|
+
toString = '.as_ref()';
|
|
1007
|
+
break;
|
|
1008
|
+
default:
|
|
1009
|
+
// no length to check so bail
|
|
1010
|
+
return '';
|
|
1011
|
+
}
|
|
1012
|
+
return helpers.buildIfBlock(indent, {
|
|
1013
|
+
condition: `${param.name}${toString}.is_empty()`,
|
|
1014
|
+
body: (indent) => `${indent.get()}return Err(azure_core::Error::message(azure_core::error::ErrorKind::Other, "parameter ${param.name} cannot be empty"));`,
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
894
1017
|
/**
|
|
895
1018
|
* constructs the body for an async client method
|
|
896
1019
|
*
|
|
@@ -901,17 +1024,18 @@ function urlVarNeedsMut(paramGroups, method) {
|
|
|
901
1024
|
* @returns the contents of the method body
|
|
902
1025
|
*/
|
|
903
1026
|
function getAsyncMethodBody(indent, use, client, method) {
|
|
904
|
-
use.add('azure_core::http', '
|
|
1027
|
+
use.add('azure_core::http', 'Method', 'Request');
|
|
905
1028
|
const paramGroups = getMethodParamGroup(method);
|
|
906
|
-
let body =
|
|
907
|
-
body +=
|
|
1029
|
+
let body = checkEmptyRequiredPathParams(indent, paramGroups.path);
|
|
1030
|
+
body += 'let options = options.unwrap_or_default();\n';
|
|
1031
|
+
body += `${indent.get()}let ctx = options.method_options.context.to_borrowed();\n`;
|
|
908
1032
|
body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}url = self.${getEndpointFieldName(client)}.clone();\n`;
|
|
909
1033
|
body += constructUrl(indent, use, method, paramGroups);
|
|
910
1034
|
body += constructRequest(indent, use, method, paramGroups, false);
|
|
911
1035
|
body += `${indent.get()}let rsp = self.pipeline.send(&ctx, &mut request).await?;\n`;
|
|
912
1036
|
body += errIfNotSuccessResponse(use, indent);
|
|
913
1037
|
let rspInto = 'rsp.into()';
|
|
914
|
-
if (method.returns.type.kind === '
|
|
1038
|
+
if (method.returns.type.kind === 'bufResponse') {
|
|
915
1039
|
rspInto = 'rsp';
|
|
916
1040
|
}
|
|
917
1041
|
body += `${indent.get()}Ok(${rspInto})\n`;
|
|
@@ -931,13 +1055,15 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
931
1055
|
throw new CodegenError('InternalError', 'paged method with no strategy NYI');
|
|
932
1056
|
}
|
|
933
1057
|
const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
|
|
934
|
-
use.add('azure_core::http', 'Method', '
|
|
1058
|
+
use.add('azure_core::http', 'Method', 'Request', 'Url');
|
|
1059
|
+
use.add('azure_core::http::pager', 'PagerResult', 'PagerState');
|
|
935
1060
|
use.add('azure_core', bodyFormat, 'Result');
|
|
936
1061
|
use.addForType(method.returns.type);
|
|
937
1062
|
use.addForType(helpers.unwrapType(method.returns.type));
|
|
938
1063
|
const paramGroups = getMethodParamGroup(method);
|
|
939
1064
|
const urlVar = 'first_url';
|
|
940
|
-
let body =
|
|
1065
|
+
let body = checkEmptyRequiredPathParams(indent, paramGroups.path);
|
|
1066
|
+
body += 'let options = options.unwrap_or_default().into_owned();\n';
|
|
941
1067
|
body += `${indent.get()}let pipeline = self.pipeline.clone();\n`;
|
|
942
1068
|
body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}${urlVar} = self.${getEndpointFieldName(client)}.clone();\n`;
|
|
943
1069
|
body += constructUrl(indent, use, method, paramGroups, urlVar);
|
|
@@ -1001,38 +1127,33 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
1001
1127
|
break;
|
|
1002
1128
|
}
|
|
1003
1129
|
}
|
|
1004
|
-
|
|
1005
|
-
let
|
|
1130
|
+
// Pipeline::send() returns a BufResponse, so no reason to declare the type if not something else.
|
|
1131
|
+
let rspType = '';
|
|
1132
|
+
let rspInto = '';
|
|
1006
1133
|
if (method.strategy.kind === 'continuationToken' && method.strategy.responseToken.kind === 'responseHeaderScalar') {
|
|
1007
1134
|
// the continuation token comes from a response header. therefore,
|
|
1008
1135
|
// we need a Response<T> so we have access to the header trait.
|
|
1009
1136
|
use.addForType(method.returns.type.type);
|
|
1010
|
-
|
|
1137
|
+
const rspTypeDecl = helpers.getTypeDeclaration(method.returns.type.type);
|
|
1138
|
+
rspType = `: ${rspTypeDecl}`;
|
|
1011
1139
|
rspInto = '.into()';
|
|
1012
1140
|
}
|
|
1013
|
-
else {
|
|
1014
|
-
// continuation token comes from the response body.
|
|
1015
|
-
// we'll deconstruct the raw response and parse it later.
|
|
1016
|
-
use.add('azure_core', 'http::RawResponse');
|
|
1017
|
-
rspType = 'RawResponse';
|
|
1018
|
-
rspInto = '';
|
|
1019
|
-
}
|
|
1020
1141
|
body += constructRequest(indent, use, method, paramGroups, true);
|
|
1021
1142
|
body += `${indent.get()}let ctx = options.method_options.context.clone();\n`;
|
|
1022
1143
|
body += `${indent.get()}let pipeline = pipeline.clone();\n`;
|
|
1023
1144
|
body += `${indent.get()}async move {\n`;
|
|
1024
|
-
body += `${indent.push().get()}let rsp
|
|
1025
|
-
if (rspType === '
|
|
1145
|
+
body += `${indent.push().get()}let rsp${rspType} = pipeline.send(&ctx, &mut request).await?${rspInto};\n`;
|
|
1146
|
+
if (rspType === '') {
|
|
1026
1147
|
body += errIfNotSuccessResponse(use, indent);
|
|
1027
1148
|
}
|
|
1028
1149
|
// check if we need to extract the next link field from the response model
|
|
1029
1150
|
if (method.strategy.kind === 'nextLink' || method.strategy.responseToken.kind === 'modelField') {
|
|
1030
|
-
use.add('azure_core', 'http::
|
|
1151
|
+
use.add('azure_core', 'http::BufResponse');
|
|
1031
1152
|
body += `${indent.get()}let (status, headers, body) = rsp.deconstruct();\n`;
|
|
1032
1153
|
body += `${indent.get()}let bytes = body.collect().await?;\n`;
|
|
1033
1154
|
const deserialize = bodyFormat === 'json' ? 'json::from_json' : 'xml::read_xml';
|
|
1034
1155
|
body += `${indent.get()}let res: ${helpers.getTypeDeclaration(helpers.unwrapType(method.returns.type))} = ${deserialize}(&bytes)?;\n`;
|
|
1035
|
-
body += `${indent.get()}let rsp =
|
|
1156
|
+
body += `${indent.get()}let rsp = BufResponse::from_bytes(status, headers, bytes).into();\n`;
|
|
1036
1157
|
}
|
|
1037
1158
|
let srcNextPage;
|
|
1038
1159
|
let nextPageValue;
|
|
@@ -1081,13 +1202,100 @@ function getPageableMethodBody(indent, use, client, method) {
|
|
|
1081
1202
|
body += `${indent.pop().get()}}))`; // end Ok/Pager::from_callback
|
|
1082
1203
|
return body;
|
|
1083
1204
|
}
|
|
1205
|
+
/**
|
|
1206
|
+
* constructs the body for an LRO client method
|
|
1207
|
+
*
|
|
1208
|
+
* @param indent the indentation helper currently in scope
|
|
1209
|
+
* @param use the use statement builder currently in scope
|
|
1210
|
+
* @param client the client to which the method belongs
|
|
1211
|
+
* @param method the method for the body to build
|
|
1212
|
+
* @returns the contents of the method body
|
|
1213
|
+
*/
|
|
1214
|
+
function getLroMethodBody(indent, use, client, method) {
|
|
1215
|
+
const bodyFormat = helpers.convertResponseFormat(method.returns.type.type.format);
|
|
1216
|
+
use.add('azure_core::http', 'Method', 'BufResponse', 'Request', 'Url');
|
|
1217
|
+
use.add('azure_core::http::headers', 'RETRY_AFTER', 'X_MS_RETRY_AFTER_MS', 'RETRY_AFTER_MS');
|
|
1218
|
+
use.add('azure_core::http::poller', 'get_retry_after', 'PollerResult', 'PollerState', 'PollerStatus', 'StatusMonitor as _');
|
|
1219
|
+
use.addForType(method.returns.type);
|
|
1220
|
+
use.addForType(helpers.unwrapType(method.returns.type));
|
|
1221
|
+
const paramGroups = getMethodParamGroup(method);
|
|
1222
|
+
const urlVar = 'url';
|
|
1223
|
+
let body = 'let options = options.unwrap_or_default().into_owned();\n';
|
|
1224
|
+
body += `${indent.get()}let pipeline = self.pipeline.clone();\n`;
|
|
1225
|
+
body += `${indent.get()}let ${urlVarNeedsMut(paramGroups, method)}${urlVar} = self.${getEndpointFieldName(client)}.clone();\n`;
|
|
1226
|
+
body += `${constructUrl(indent, use, method, paramGroups, urlVar)}\n\n`;
|
|
1227
|
+
if (paramGroups.apiVersion) {
|
|
1228
|
+
body += `${indent.get()}let ${paramGroups.apiVersion.name} = ${getHeaderPathQueryParamValue(use, paramGroups.apiVersion, true)}.clone();\n\n`;
|
|
1229
|
+
}
|
|
1230
|
+
body += `${indent.get()}Ok(${method.returns.type.name}::from_callback(\n`;
|
|
1231
|
+
body += `${indent.push().get()}move |next_link: PollerState<Url>| {\n`;
|
|
1232
|
+
body += `${indent.push().get()}let (mut request, next_link) = ${helpers.buildMatch(indent, 'next_link', [{
|
|
1233
|
+
pattern: `PollerState::More(next_link)`,
|
|
1234
|
+
body: (indent) => {
|
|
1235
|
+
let body = '';
|
|
1236
|
+
if (paramGroups.apiVersion) {
|
|
1237
|
+
body += `${indent.get()}let qp = next_link.query_pairs().filter(|(name, _)| name.ne("api-version"));\n`;
|
|
1238
|
+
}
|
|
1239
|
+
body += `${indent.get()}let mut next_link = next_link.clone();\n`;
|
|
1240
|
+
if (paramGroups.apiVersion) {
|
|
1241
|
+
body += `${indent.get()}next_link.query_pairs_mut().clear().extend_pairs(qp).append_pair("api-version", &${paramGroups.apiVersion.name});\n\n`;
|
|
1242
|
+
}
|
|
1243
|
+
body += `${indent.get()}let ${paramGroups.header.length > 0 ? 'mut ' : ''}request = Request::new(next_link.clone(), Method::Get);`;
|
|
1244
|
+
body += `\n${applyHeaderParams(indent, use, method, paramGroups, true)}\n\n`;
|
|
1245
|
+
body += `${indent.get()}(request, next_link)\n`;
|
|
1246
|
+
return body;
|
|
1247
|
+
},
|
|
1248
|
+
}, {
|
|
1249
|
+
pattern: 'PollerState::Initial',
|
|
1250
|
+
body: (indent) => {
|
|
1251
|
+
let body = `${constructRequest(indent, use, method, paramGroups, true, true, false)}\n`;
|
|
1252
|
+
body += `${indent.get()}(request, url.clone())\n`;
|
|
1253
|
+
return body;
|
|
1254
|
+
},
|
|
1255
|
+
}])};\n\n`;
|
|
1256
|
+
body += `${indent.get()}let ctx = options.method_options.context.clone();\n`;
|
|
1257
|
+
body += `${indent.get()}let pipeline = pipeline.clone();\n`;
|
|
1258
|
+
body += `${indent.get()}async move {\n`;
|
|
1259
|
+
body += `${indent.push().get()}let rsp = pipeline.send(&ctx, &mut request).await?;\n`;
|
|
1260
|
+
body += `${indent.get()}let (status, headers, body) = rsp.deconstruct();\n`;
|
|
1261
|
+
body += `${indent.get()}let retry_after = get_retry_after(&headers, &[X_MS_RETRY_AFTER_MS, RETRY_AFTER_MS, RETRY_AFTER], &options.poller_options);\n`;
|
|
1262
|
+
body += `${indent.get()}let bytes = body.collect().await?;\n`;
|
|
1263
|
+
let deserialize = '';
|
|
1264
|
+
if (bodyFormat === 'json') {
|
|
1265
|
+
use.add('azure_core', 'json');
|
|
1266
|
+
deserialize = 'json::from_json';
|
|
1267
|
+
}
|
|
1268
|
+
else {
|
|
1269
|
+
deserialize = 'xml::read_xml';
|
|
1270
|
+
}
|
|
1271
|
+
body += `${indent.get()}let res: ${helpers.getTypeDeclaration(helpers.unwrapType(method.returns.type))} = ${deserialize}(&bytes)?;\n`;
|
|
1272
|
+
body += `${indent.get()}let rsp = BufResponse::from_bytes(status, headers, bytes).into();\n`;
|
|
1273
|
+
body += `${indent.get()}Ok(${helpers.buildMatch(indent, 'res.status()', [{
|
|
1274
|
+
pattern: `PollerStatus::InProgress`,
|
|
1275
|
+
body: (indent) => {
|
|
1276
|
+
return `${indent.get()}response: rsp, retry_after, next: next_link\n`;
|
|
1277
|
+
},
|
|
1278
|
+
returns: 'PollerResult::InProgress'
|
|
1279
|
+
}, {
|
|
1280
|
+
pattern: '_',
|
|
1281
|
+
body: (indent) => {
|
|
1282
|
+
return `${indent.get()}response: rsp`;
|
|
1283
|
+
},
|
|
1284
|
+
returns: 'PollerResult::Done'
|
|
1285
|
+
}])})\n`;
|
|
1286
|
+
body += `${indent.pop().get()}}\n`; // end async move
|
|
1287
|
+
body += `${indent.pop().get()}},\n`; // end move
|
|
1288
|
+
body += `${indent.get()}None,\n`;
|
|
1289
|
+
body += `${indent.pop().get()}))`; // end Ok/Poller::from_callback
|
|
1290
|
+
return body;
|
|
1291
|
+
}
|
|
1084
1292
|
/**
|
|
1085
1293
|
* contains the code to use when populating a client endpoint parameter value
|
|
1086
1294
|
* from a parameter of that type.
|
|
1087
1295
|
* @param param the param for which to get the value
|
|
1088
1296
|
* @returns the code to use for the param's value
|
|
1089
1297
|
*/
|
|
1090
|
-
function
|
|
1298
|
+
function getClientSupplementalEndpointParamValue(param) {
|
|
1091
1299
|
let paramName = param.name;
|
|
1092
1300
|
if (param.optional) {
|
|
1093
1301
|
paramName = 'options.' + paramName;
|
|
@@ -1179,8 +1387,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf) {
|
|
|
1179
1387
|
return encodeBytes(paramType, paramName);
|
|
1180
1388
|
case 'enum':
|
|
1181
1389
|
case 'scalar':
|
|
1182
|
-
if (paramType.kind === 'enum' && param.kind === 'queryScalar') {
|
|
1183
|
-
// append_pair
|
|
1390
|
+
if (paramType.kind === 'enum' && (param.kind === 'pathScalar' || param.kind === 'queryScalar')) {
|
|
1391
|
+
// append_pair and path.replace() want a reference to the string
|
|
1184
1392
|
// TODO: https://github.com/Azure/typespec-rust/issues/25
|
|
1185
1393
|
return `${paramName}.as_ref()`;
|
|
1186
1394
|
}
|
|
@@ -1231,9 +1439,4 @@ function nonCopyableType(type) {
|
|
|
1231
1439
|
function isClientMethodOptions(type) {
|
|
1232
1440
|
return type.kind === 'external' && type.name === 'ClientMethodOptions';
|
|
1233
1441
|
}
|
|
1234
|
-
/** returns true if the type is a credential */
|
|
1235
|
-
function isCredential(type) {
|
|
1236
|
-
const unwrappedType = helpers.unwrapType(type);
|
|
1237
|
-
return unwrappedType.kind === 'tokenCredential';
|
|
1238
|
-
}
|
|
1239
1442
|
//# sourceMappingURL=clients.js.map
|