@azure-tools/typespec-rust 0.36.0 → 0.38.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/clients.d.ts +4 -4
- package/dist/src/codegen/clients.d.ts.map +1 -1
- package/dist/src/codegen/clients.js +208 -88
- package/dist/src/codegen/clients.js.map +1 -1
- package/dist/src/codegen/codeGenerator.d.ts +6 -0
- package/dist/src/codegen/codeGenerator.d.ts.map +1 -1
- package/dist/src/codegen/codeGenerator.js +112 -32
- package/dist/src/codegen/codeGenerator.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 +57 -15
- package/dist/src/codegen/context.js.map +1 -1
- package/dist/src/codegen/docTests.d.ts +1 -2
- package/dist/src/codegen/docTests.d.ts.map +1 -1
- package/dist/src/codegen/docTests.js +13 -3
- package/dist/src/codegen/docTests.js.map +1 -1
- package/dist/src/codegen/enums.d.ts +4 -4
- package/dist/src/codegen/enums.d.ts.map +1 -1
- package/dist/src/codegen/enums.js +21 -21
- package/dist/src/codegen/enums.js.map +1 -1
- package/dist/src/codegen/headerTraits.d.ts +2 -2
- package/dist/src/codegen/headerTraits.d.ts.map +1 -1
- package/dist/src/codegen/headerTraits.js +17 -9
- package/dist/src/codegen/headerTraits.js.map +1 -1
- package/dist/src/codegen/helpers.d.ts +12 -3
- package/dist/src/codegen/helpers.d.ts.map +1 -1
- package/dist/src/codegen/helpers.js +22 -13
- package/dist/src/codegen/helpers.js.map +1 -1
- package/dist/src/codegen/lib.d.ts +3 -1
- package/dist/src/codegen/lib.d.ts.map +1 -1
- package/dist/src/codegen/lib.js +5 -1
- package/dist/src/codegen/lib.js.map +1 -1
- package/dist/src/codegen/mod.d.ts +9 -2
- package/dist/src/codegen/mod.d.ts.map +1 -1
- package/dist/src/codegen/mod.js +25 -9
- package/dist/src/codegen/mod.js.map +1 -1
- package/dist/src/codegen/models.d.ts +4 -4
- package/dist/src/codegen/models.d.ts.map +1 -1
- package/dist/src/codegen/models.js +96 -39
- package/dist/src/codegen/models.js.map +1 -1
- package/dist/src/codegen/unions.d.ts +4 -4
- package/dist/src/codegen/unions.d.ts.map +1 -1
- package/dist/src/codegen/unions.js +81 -62
- package/dist/src/codegen/unions.js.map +1 -1
- package/dist/src/codegen/use.d.ts +4 -2
- package/dist/src/codegen/use.d.ts.map +1 -1
- package/dist/src/codegen/use.js +22 -26
- package/dist/src/codegen/use.js.map +1 -1
- package/dist/src/codemodel/client.d.ts +32 -16
- package/dist/src/codemodel/client.d.ts.map +1 -1
- package/dist/src/codemodel/client.js +11 -7
- package/dist/src/codemodel/client.js.map +1 -1
- package/dist/src/codemodel/crate.d.ts +42 -12
- package/dist/src/codemodel/crate.d.ts.map +1 -1
- package/dist/src/codemodel/crate.js +21 -46
- package/dist/src/codemodel/crate.js.map +1 -1
- package/dist/src/codemodel/types.d.ts +69 -38
- package/dist/src/codemodel/types.d.ts.map +1 -1
- package/dist/src/codemodel/types.js +31 -10
- package/dist/src/codemodel/types.js.map +1 -1
- package/dist/src/emitter.d.ts.map +1 -1
- package/dist/src/emitter.js +40 -12
- package/dist/src/emitter.js.map +1 -1
- package/dist/src/lib.d.ts +2 -0
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +6 -0
- package/dist/src/lib.js.map +1 -1
- package/dist/src/tcgcadapter/adapter.d.ts +76 -13
- package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
- package/dist/src/tcgcadapter/adapter.js +777 -190
- package/dist/src/tcgcadapter/adapter.js.map +1 -1
- package/dist/src/utils/utils.d.ts +23 -4
- package/dist/src/utils/utils.d.ts.map +1 -1
- package/dist/src/utils/utils.js +54 -23
- package/dist/src/utils/utils.js.map +1 -1
- package/package.json +17 -17
|
@@ -5,13 +5,13 @@ export interface ClientModules {
|
|
|
5
5
|
/** the list of client modules */
|
|
6
6
|
modules: Array<helpers.Module>;
|
|
7
7
|
/** the client method options module */
|
|
8
|
-
options
|
|
8
|
+
options?: helpers.Module;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* emits the content for all client files
|
|
12
12
|
*
|
|
13
|
-
* @param
|
|
14
|
-
* @returns client content or undefined if the
|
|
13
|
+
* @param module the module for which to emit clients
|
|
14
|
+
* @returns client content or undefined if the module contains no clients
|
|
15
15
|
*/
|
|
16
|
-
export declare function emitClients(
|
|
16
|
+
export declare function emitClients(module: rust.ModuleContainer): ClientModules | undefined;
|
|
17
17
|
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AASA,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;
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../src/codegen/clients.ts"],"names":[],"mappings":"AASA,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,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,eAAe,GAAG,aAAa,GAAG,SAAS,CA+UnF"}
|
|
@@ -13,11 +13,11 @@ import * as utils from '../utils/utils.js';
|
|
|
13
13
|
/**
|
|
14
14
|
* emits the content for all client files
|
|
15
15
|
*
|
|
16
|
-
* @param
|
|
17
|
-
* @returns client content or undefined if the
|
|
16
|
+
* @param module the module for which to emit clients
|
|
17
|
+
* @returns client content or undefined if the module contains no clients
|
|
18
18
|
*/
|
|
19
|
-
export function emitClients(
|
|
20
|
-
if (
|
|
19
|
+
export function emitClients(module) {
|
|
20
|
+
if (module.clients.length === 0) {
|
|
21
21
|
return undefined;
|
|
22
22
|
}
|
|
23
23
|
// returns true if the client options type needs to explicitly implement Default
|
|
@@ -34,8 +34,8 @@ export function emitClients(crate) {
|
|
|
34
34
|
};
|
|
35
35
|
const clientModules = new Array();
|
|
36
36
|
// emit the clients, one file per client
|
|
37
|
-
for (const client of
|
|
38
|
-
const use = new Use('clients');
|
|
37
|
+
for (const client of module.clients) {
|
|
38
|
+
const use = new Use(module, 'clients');
|
|
39
39
|
const indent = new helpers.indentation();
|
|
40
40
|
let body = helpers.formatDocComment(client.docs);
|
|
41
41
|
use.add('azure_core', 'tracing');
|
|
@@ -163,6 +163,7 @@ export function emitClients(crate) {
|
|
|
163
163
|
body += `${indent.get()}pub fn endpoint(&self) -> &Url {\n`;
|
|
164
164
|
body += `${indent.push().get()}&self.${client.endpoint.name}\n`;
|
|
165
165
|
body += `${indent.pop().get()}}\n\n`;
|
|
166
|
+
const crate = helpers.getCrate(module);
|
|
166
167
|
for (let i = 0; i < client.methods.length; ++i) {
|
|
167
168
|
const method = client.methods[i];
|
|
168
169
|
const returnType = helpers.getTypeDeclaration(method.returns);
|
|
@@ -231,6 +232,42 @@ export function emitClients(crate) {
|
|
|
231
232
|
}
|
|
232
233
|
}
|
|
233
234
|
body += '}\n\n'; // end client impl
|
|
235
|
+
// Emit pub(crate) const declarations for fields with default value constants.
|
|
236
|
+
//
|
|
237
|
+
// These constants are ALWAYS emitted, even when the options type is suppressed.
|
|
238
|
+
// In SDK crates with suppressed options, SDK authors need these constants to
|
|
239
|
+
// reference TypeSpec-defined default values (e.g., api-version) in their
|
|
240
|
+
// hand-authored Default impl. Suppressing them would force hardcoding.
|
|
241
|
+
//
|
|
242
|
+
// Visibility design:
|
|
243
|
+
// - Non-suppressed: constant is referenced by the generated Default impl, so
|
|
244
|
+
// it's alive and no dead_code suppression is needed.
|
|
245
|
+
// - Suppressed: the generated options type doesn't exist — SDK authors provide
|
|
246
|
+
// their own. The constant is a convenience they SHOULD use, but may not.
|
|
247
|
+
// #[allow(dead_code)] is appropriate here (parallels std library patterns).
|
|
248
|
+
if (client.constructable) {
|
|
249
|
+
const isSuppressed = client.constructable.suppressed === 'yes';
|
|
250
|
+
for (const field of client.constructable.options.type.fields) {
|
|
251
|
+
if (field.defaultValueConstant) {
|
|
252
|
+
if (isSuppressed) {
|
|
253
|
+
// Plain text doc comment — the options type doesn't exist when suppressed,
|
|
254
|
+
// so intra-doc links would be broken.
|
|
255
|
+
body += `/// Default value for \`${client.constructable.options.type.name}::${field.name}\`.\n`;
|
|
256
|
+
body += `///\n`;
|
|
257
|
+
body += `/// This constant is available for SDK authors to use in hand-authored code.\n`;
|
|
258
|
+
body += `/// When the options type is suppressed (via \`@access(Access.internal)\`), the\n`;
|
|
259
|
+
body += `/// SDK author provides a custom options type and should reference this constant\n`;
|
|
260
|
+
body += `/// in their \`Default\` implementation rather than hardcoding the value.\n`;
|
|
261
|
+
body += `#[allow(dead_code)]\n`;
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// Intra-doc link — the options type exists and the link resolves.
|
|
265
|
+
body += `/// Default value for [\`${client.constructable.options.type.name}::${field.name}\`].\n`;
|
|
266
|
+
}
|
|
267
|
+
body += `pub(crate) const ${field.defaultValueConstant.name}: &str = "${field.defaultValueConstant.value}";\n\n`;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
234
271
|
// only implement Default when there's more than one field.
|
|
235
272
|
// for the single-case field we just derive Default.
|
|
236
273
|
if (client.constructable && clientOptionsImplDefault(client.constructable)) {
|
|
@@ -256,7 +293,16 @@ export function emitClients(crate) {
|
|
|
256
293
|
// add using for method_options as required
|
|
257
294
|
for (const method of client.methods) {
|
|
258
295
|
if (method.kind !== 'clientaccessor') {
|
|
259
|
-
|
|
296
|
+
// client method options types are always in the same module as their client method
|
|
297
|
+
use.add(`${utils.buildImportPath(client.module, client.module)}::models`, method.options.type.type.name);
|
|
298
|
+
// add imports for parameter group types
|
|
299
|
+
const seenGroups = new Set();
|
|
300
|
+
for (const param of method.params) {
|
|
301
|
+
if (param.group && !seenGroups.has(param.group.type.name)) {
|
|
302
|
+
seenGroups.add(param.group.type.name);
|
|
303
|
+
use.add(`${utils.buildImportPath(client.module, client.module)}::models`, param.group.type.name);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
260
306
|
}
|
|
261
307
|
}
|
|
262
308
|
let content = helpers.contentPreamble();
|
|
@@ -271,64 +317,102 @@ export function emitClients(crate) {
|
|
|
271
317
|
}
|
|
272
318
|
return {
|
|
273
319
|
modules: clientModules,
|
|
274
|
-
options: getMethodOptions(
|
|
320
|
+
options: getMethodOptions(module),
|
|
275
321
|
};
|
|
276
322
|
}
|
|
277
|
-
function getMethodOptions(
|
|
278
|
-
const use = new Use('modelsOther');
|
|
323
|
+
function getMethodOptions(module) {
|
|
324
|
+
const use = new Use(module, 'modelsOther');
|
|
279
325
|
const indent = new helpers.indentation();
|
|
280
326
|
const visTracker = new helpers.VisibilityTracker();
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
327
|
+
// collect all struct blocks so they can be sorted by name
|
|
328
|
+
const structBlocks = [];
|
|
329
|
+
for (const client of module.clients) {
|
|
330
|
+
for (const method of client.methods) {
|
|
285
331
|
if (method.kind === 'clientaccessor') {
|
|
286
332
|
continue;
|
|
287
333
|
}
|
|
288
|
-
|
|
334
|
+
// method options struct
|
|
335
|
+
let block = '';
|
|
336
|
+
const optionsStruct = method.options.type.type;
|
|
337
|
+
block += helpers.formatDocComment(optionsStruct.docs);
|
|
289
338
|
use.add('azure_core::fmt', 'SafeDebug');
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
visTracker.update(
|
|
293
|
-
for (let i = 0; i <
|
|
294
|
-
const field =
|
|
339
|
+
block += '#[derive(Clone, Default, SafeDebug)]\n';
|
|
340
|
+
block += `${helpers.emitVisibility(optionsStruct.visibility)}struct ${helpers.getTypeDeclaration(optionsStruct)} {\n`;
|
|
341
|
+
visTracker.update(optionsStruct.visibility);
|
|
342
|
+
for (let i = 0; i < optionsStruct.fields.length; ++i) {
|
|
343
|
+
const field = optionsStruct.fields[i];
|
|
295
344
|
use.addForType(field.type);
|
|
296
345
|
const fieldDocs = helpers.formatDocComment(field.docs);
|
|
297
346
|
if (fieldDocs.length > 0) {
|
|
298
|
-
|
|
347
|
+
block += `${indent.get()}${fieldDocs}`;
|
|
299
348
|
}
|
|
300
|
-
|
|
301
|
-
if (i + 1 <
|
|
302
|
-
|
|
349
|
+
block += `${indent.get()}${helpers.emitVisibility(method.visibility)}${field.name}: ${helpers.getTypeDeclaration(field.type)},\n`;
|
|
350
|
+
if (i + 1 < optionsStruct.fields.length) {
|
|
351
|
+
block += '\n';
|
|
303
352
|
}
|
|
304
353
|
}
|
|
305
|
-
|
|
354
|
+
block += '}\n';
|
|
306
355
|
if (method.kind === 'pageable' || method.kind === 'lro') {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
356
|
+
block += '\n';
|
|
357
|
+
block += `impl ${helpers.getTypeDeclaration(optionsStruct, 'anonymous')} {\n`;
|
|
358
|
+
const wrappedTypeName = helpers.wrapInBackTicks(helpers.getTypeDeclaration(optionsStruct, 'omit'));
|
|
359
|
+
block += `${indent.get()}/// Transforms this [${wrappedTypeName}] into a new ${wrappedTypeName} that owns the underlying data, cloning it if necessary.\n`;
|
|
360
|
+
block += `${indent.get()}pub fn into_owned(self) -> ${optionsStruct.name}<'static> {\n`;
|
|
361
|
+
block += `${indent.push().get()}${optionsStruct.name} {\n`;
|
|
312
362
|
indent.push();
|
|
313
|
-
for (const field of
|
|
363
|
+
for (const field of optionsStruct.fields) {
|
|
314
364
|
if (field.type.kind === 'clientMethodOptions' || field.type.kind === 'pagerOptions' || field.type.kind === 'pollerOptions') {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
365
|
+
block += `${indent.get()}${field.name}: ${field.type.name} {\n`;
|
|
366
|
+
block += `${indent.push().get()}context: self.${field.name}.context.into_owned(),\n`;
|
|
367
|
+
block += `${indent.get()}..self.${field.name}\n`;
|
|
368
|
+
block += `${indent.pop().get()}},\n`;
|
|
319
369
|
continue;
|
|
320
370
|
}
|
|
321
|
-
|
|
371
|
+
block += `${indent.get()}${field.name}: self.${field.name},\n`;
|
|
322
372
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
373
|
+
block += `${indent.pop().get()}}\n`;
|
|
374
|
+
block += `${indent.pop().get()}}\n`;
|
|
375
|
+
block += '}\n';
|
|
326
376
|
}
|
|
327
|
-
|
|
328
|
-
|
|
377
|
+
structBlocks.push({ name: optionsStruct.name, body: block });
|
|
378
|
+
// parameter group structs
|
|
379
|
+
const seenGroups = new Set();
|
|
380
|
+
for (const param of method.params) {
|
|
381
|
+
if (param.group) {
|
|
382
|
+
seenGroups.add(param.group);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
for (const group of seenGroups) {
|
|
386
|
+
const groupParams = method.params.filter(p => p.group === group);
|
|
387
|
+
let groupBlock = '';
|
|
388
|
+
groupBlock += helpers.formatDocComment(group.type.docs);
|
|
389
|
+
use.add('azure_core::fmt', 'SafeDebug');
|
|
390
|
+
groupBlock += '#[derive(Clone, SafeDebug)]\n';
|
|
391
|
+
groupBlock += `${helpers.emitVisibility(group.type.visibility)}struct ${group.type.name}${group.type.lifetime ? `<${group.type.lifetime.name}>` : ''} {\n`;
|
|
392
|
+
visTracker.update(group.type.visibility);
|
|
393
|
+
for (let i = 0; i < groupParams.length; i++) {
|
|
394
|
+
const field = groupParams[i];
|
|
395
|
+
use.addForType(field.type);
|
|
396
|
+
const fieldDocs = helpers.formatDocComment(field.docs);
|
|
397
|
+
if (fieldDocs.length > 0) {
|
|
398
|
+
if (i > 0) {
|
|
399
|
+
groupBlock += '\n';
|
|
400
|
+
}
|
|
401
|
+
groupBlock += `${indent.get()}${fieldDocs}`;
|
|
402
|
+
}
|
|
403
|
+
groupBlock += `${indent.get()}${helpers.emitVisibility(group.type.visibility)}${field.name}: ${helpers.getTypeDeclaration(field.type)},\n`;
|
|
404
|
+
}
|
|
405
|
+
groupBlock += '}\n';
|
|
406
|
+
structBlocks.push({ name: group.type.name, body: groupBlock });
|
|
329
407
|
}
|
|
330
408
|
}
|
|
331
409
|
}
|
|
410
|
+
structBlocks.sort((a, b) => helpers.sortAscending(a.name, b.name));
|
|
411
|
+
const body = structBlocks.map((b) => b.body).join('\n');
|
|
412
|
+
if (body === '') {
|
|
413
|
+
// client is top-level only, no methods just accessors
|
|
414
|
+
return undefined;
|
|
415
|
+
}
|
|
332
416
|
let content = helpers.contentPreamble();
|
|
333
417
|
content += use.text();
|
|
334
418
|
content += body;
|
|
@@ -351,7 +435,17 @@ function getParamsBlockDocComment(indent, callable) {
|
|
|
351
435
|
return `* ${helpers.wrapInBackTicks(paramName)} - `;
|
|
352
436
|
};
|
|
353
437
|
let paramsContent = '';
|
|
438
|
+
const documentedGroups = new Set();
|
|
354
439
|
for (const param of callable.params) {
|
|
440
|
+
if ('group' in param && param.group) {
|
|
441
|
+
// required parameter group appears as a single param in the method sig
|
|
442
|
+
const group = param.group;
|
|
443
|
+
if (!documentedGroups.has(group.name)) {
|
|
444
|
+
documentedGroups.add(group.name);
|
|
445
|
+
paramsContent += helpers.formatDocComment(group.docs, false, formatParamBullet(group.name), indent);
|
|
446
|
+
}
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
355
449
|
let optional = false;
|
|
356
450
|
if ('optional' in param) {
|
|
357
451
|
optional = param.optional;
|
|
@@ -426,7 +520,17 @@ function getMethodParamsCountAndSig(method, use) {
|
|
|
426
520
|
}
|
|
427
521
|
}
|
|
428
522
|
else {
|
|
523
|
+
const emittedGroups = new Set();
|
|
429
524
|
for (const param of method.params) {
|
|
525
|
+
if (param.group) {
|
|
526
|
+
if (!emittedGroups.has(param.group.name)) {
|
|
527
|
+
emittedGroups.add(param.group.name);
|
|
528
|
+
// required parameter group appears as a single struct parameter in the method signature
|
|
529
|
+
paramsSig.push(`${param.group.name}: ${helpers.getTypeDeclaration(param.group.type, 'anonymous')}`);
|
|
530
|
+
++count;
|
|
531
|
+
}
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
430
534
|
const paramType = helpers.unwrapType(param.type);
|
|
431
535
|
if (paramType.kind === 'literal') {
|
|
432
536
|
// literal params are embedded directly in the code (e.g. accept header param)
|
|
@@ -444,7 +548,7 @@ function getMethodParamsCountAndSig(method, use) {
|
|
|
444
548
|
++count;
|
|
445
549
|
}
|
|
446
550
|
}
|
|
447
|
-
paramsSig.push(
|
|
551
|
+
paramsSig.push(`${method.options.name}: ${helpers.getTypeDeclaration(method.options.type, 'anonymous')}`);
|
|
448
552
|
++count;
|
|
449
553
|
}
|
|
450
554
|
return { count: count, sig: paramsSig.join(', ') };
|
|
@@ -453,11 +557,11 @@ function getMethodParamsCountAndSig(method, use) {
|
|
|
453
557
|
* returns documentation for header trait access if the method has response headers.
|
|
454
558
|
*
|
|
455
559
|
* @param indent the current indentation level
|
|
456
|
-
* @param
|
|
560
|
+
* @param module the module to which method belongs
|
|
457
561
|
* @param method the method for which to generate header trait documentation
|
|
458
562
|
* @returns the header trait documentation or empty string if not applicable
|
|
459
563
|
*/
|
|
460
|
-
function getHeaderTraitDocComment(indent,
|
|
564
|
+
function getHeaderTraitDocComment(indent, module, method) {
|
|
461
565
|
if (!method.responseHeaders) {
|
|
462
566
|
return '';
|
|
463
567
|
}
|
|
@@ -479,15 +583,15 @@ function getHeaderTraitDocComment(indent, crate, method) {
|
|
|
479
583
|
headerDocs += `${indent.get()}/// The returned [${helpers.wrapInBackTicks(returnType)}](azure_core::http::${returnType}) implements the [${helpers.wrapInBackTicks(traitName)}] trait, which provides\n`;
|
|
480
584
|
headerDocs += `${indent.get()}/// access to response headers. For example:\n`;
|
|
481
585
|
headerDocs += `${indent.get()}///\n`;
|
|
482
|
-
headerDocs += emitHeaderTraitDocExample(
|
|
586
|
+
headerDocs += emitHeaderTraitDocExample(method.responseHeaders, indent);
|
|
483
587
|
headerDocs += `${indent.get()}///\n`;
|
|
484
588
|
headerDocs += `${indent.get()}/// ### Available headers\n`;
|
|
485
589
|
// List all available headers
|
|
486
590
|
for (const header of method.responseHeaders.headers) {
|
|
487
|
-
headerDocs += `${indent.get()}/// * [${helpers.wrapInBackTicks(header.name)}()](
|
|
591
|
+
headerDocs += `${indent.get()}/// * [${helpers.wrapInBackTicks(header.name)}()](${utils.buildImportPath(module, module)}::models::${traitName}::${header.name}) - ${header.header}\n`;
|
|
488
592
|
}
|
|
489
593
|
headerDocs += `${indent.get()}///\n`;
|
|
490
|
-
headerDocs += `${indent.get()}/// [${helpers.wrapInBackTicks(traitName)}]:
|
|
594
|
+
headerDocs += `${indent.get()}/// [${helpers.wrapInBackTicks(traitName)}]: ${utils.buildImportPath(module, module)}::models::${traitName}\n`;
|
|
491
595
|
return headerDocs;
|
|
492
596
|
}
|
|
493
597
|
/**
|
|
@@ -565,6 +669,17 @@ function getClientAccessorMethodBody(indent, client, clientAccessor) {
|
|
|
565
669
|
if (clientAccessor.returns.fields.find((e) => e.name === field.name)) {
|
|
566
670
|
initFields.push(`${field.name}: self.${field.name}${nonCopyableType(field.type) ? '.clone()' : ''}`);
|
|
567
671
|
}
|
|
672
|
+
else {
|
|
673
|
+
// by convention the fields propagated from parent to child have the same name.
|
|
674
|
+
// there is an edge-case though for multi-client where the parent client contains
|
|
675
|
+
// multiple api-version params, one per child client. in this case, the param
|
|
676
|
+
// names include the client name as a prefix to disambiguate them. we check for
|
|
677
|
+
// that case here.
|
|
678
|
+
const disambiguatedField = clientAccessor.returns.fields.find((e) => utils.deduplicateClientFieldName(clientAccessor.returns, e.name) === field.name);
|
|
679
|
+
if (disambiguatedField) {
|
|
680
|
+
initFields.push(`${disambiguatedField.name}: self.${field.name}${nonCopyableType(field.type) ? '.clone()' : ''}`);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
568
683
|
}
|
|
569
684
|
// sort the fields as the fields in the client are also sorted
|
|
570
685
|
initFields.sort();
|
|
@@ -683,8 +798,8 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
683
798
|
throw new CodegenError('InternalError', 'too many HTTP path chunks');
|
|
684
799
|
}
|
|
685
800
|
let body = '';
|
|
686
|
-
// if path is just "/" no need to set it again, we're already there
|
|
687
|
-
if (pathChunks[0] !== '/') {
|
|
801
|
+
// if path is just "/" or empty, no need to set it again, we're already there
|
|
802
|
+
if (pathChunks[0] !== '/' && pathChunks[0] !== '') {
|
|
688
803
|
use.add('azure_core::http', 'UrlExt');
|
|
689
804
|
let path = `"${pathChunks[0]}"`;
|
|
690
805
|
if (paramGroups.path.length === 0) {
|
|
@@ -704,50 +819,49 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
704
819
|
let wrapSortedVec = (s) => s;
|
|
705
820
|
let paramExpression;
|
|
706
821
|
if (pathParam.kind === 'pathHashMap') {
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
+ `${indent.get()}${pathParam.name}
|
|
710
|
-
+ `${s}`
|
|
711
|
-
+ `${indent.pop().get()}}`;
|
|
822
|
+
const pathParamRef = qualifiedParamName(pathParam);
|
|
823
|
+
wrapSortedVec = (s) => `${indent.get()}let mut ${pathParam.name} = ${pathParamRef}.iter().collect::<Vec<_>>();\n`
|
|
824
|
+
+ `${indent.get()}${pathParam.name}.sort_by_key(|p| p.0);\n${s}`;
|
|
712
825
|
const kEqualsV = '"{k}={v}"';
|
|
713
826
|
const kCommaV = '"{k},{v}"';
|
|
714
|
-
paramExpression = `&${pathParam.name}
|
|
827
|
+
paramExpression = `&${pathParam.name}.iter().map(|(k,v)| `
|
|
715
828
|
+ (pathParam.explode
|
|
716
829
|
? `format!(${kEqualsV})).collect::<Vec<_>>().join(",")`
|
|
717
830
|
: `format!(${kCommaV})).collect::<Vec<_>>().join(",")`);
|
|
718
831
|
switch (pathParam.style) {
|
|
719
832
|
case 'path':
|
|
720
|
-
paramExpression = `&format!("/{}", ${pathParam.name}
|
|
833
|
+
paramExpression = `&format!("/{}", ${pathParam.name}.iter().map(|(k,v)| `
|
|
721
834
|
+ (pathParam.explode
|
|
722
835
|
? `format!(${kEqualsV})).collect::<Vec<_>>().join("/"))`
|
|
723
836
|
: `format!(${kCommaV})).collect::<Vec<_>>().join(","))`);
|
|
724
837
|
break;
|
|
725
838
|
case 'label':
|
|
726
|
-
paramExpression = `&format!(".{}", ${pathParam.name}
|
|
839
|
+
paramExpression = `&format!(".{}", ${pathParam.name}.iter().map(|(k,v)| `
|
|
727
840
|
+ (pathParam.explode
|
|
728
841
|
? `format!(${kEqualsV})).collect::<Vec<_>>().join("."))`
|
|
729
842
|
: `format!(${kCommaV})).collect::<Vec<_>>().join(","))`);
|
|
730
843
|
break;
|
|
731
844
|
case 'matrix':
|
|
732
845
|
paramExpression = pathParam.explode
|
|
733
|
-
? (`&format!(";{}", ${pathParam.name}
|
|
846
|
+
? (`&format!(";{}", ${pathParam.name}.into_iter().map(|(k,v)| `
|
|
734
847
|
+ `format!(${kEqualsV})).collect::<Vec<_>>().join(";"))`)
|
|
735
|
-
: (`&format!(";${pathParam.name}={}", ${pathParam.name}
|
|
848
|
+
: (`&format!(";${pathParam.name}={}", ${pathParam.name}.into_iter().map(|(k,v)| `
|
|
736
849
|
+ `format!(${kCommaV})).collect::<Vec<_>>().join(","))`);
|
|
737
850
|
break;
|
|
738
851
|
}
|
|
739
852
|
}
|
|
740
853
|
else if (pathParam.kind === 'pathCollection') {
|
|
741
|
-
|
|
854
|
+
const pathParamRef = qualifiedParamName(pathParam);
|
|
855
|
+
paramExpression = `&${pathParamRef}.join(",")`;
|
|
742
856
|
switch (pathParam.style) {
|
|
743
857
|
case 'path':
|
|
744
|
-
paramExpression = `&format!("/{}", ${
|
|
858
|
+
paramExpression = `&format!("/{}", ${pathParamRef}.join("${pathParam.explode ? '/' : ','}"))`;
|
|
745
859
|
break;
|
|
746
860
|
case 'label':
|
|
747
|
-
paramExpression = `&format!(".{}", ${
|
|
861
|
+
paramExpression = `&format!(".{}", ${pathParamRef}.join("${pathParam.explode ? '.' : ','}"))`;
|
|
748
862
|
break;
|
|
749
863
|
case 'matrix':
|
|
750
|
-
paramExpression = `&format!(";${pathParam.name}={}", ${
|
|
864
|
+
paramExpression = `&format!(";${pathParam.name}={}", ${pathParamRef}.join(`
|
|
751
865
|
+ `"${pathParam.explode ? `;${pathParam.name}=` : ','}"))`;
|
|
752
866
|
break;
|
|
753
867
|
}
|
|
@@ -822,8 +936,9 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
822
936
|
for (const queryParam of paramGroups.query) {
|
|
823
937
|
if (queryParam.kind === 'queryCollection' && queryParam.format === 'multi') {
|
|
824
938
|
body += getParamValueHelper(indent, queryParam, () => {
|
|
939
|
+
const queryParamRef = qualifiedParamName(queryParam);
|
|
825
940
|
const valueVar = queryParam.name[0];
|
|
826
|
-
let text = `${indent.get()}for ${valueVar} in ${
|
|
941
|
+
let text = `${indent.get()}for ${valueVar} in ${queryParamRef}.iter() {\n`;
|
|
827
942
|
// if queryParam is a &[&str] then we'll need to deref the iterator
|
|
828
943
|
const deref = utils.asTypeOf(queryParam.type, 'str', 'ref', 'slice', 'ref') ? '*' : '';
|
|
829
944
|
text += `${indent.push().get()}query_builder.append_pair("${queryParam.key}", ${deref}${getHeaderPathQueryParamValue(use, queryParam, !queryParam.optional, false, valueVar)});\n`;
|
|
@@ -833,19 +948,14 @@ function constructUrl(indent, use, method, paramGroups, urlVarName) {
|
|
|
833
948
|
}
|
|
834
949
|
else if (queryParam.kind === 'queryHashMap') {
|
|
835
950
|
body += getParamValueHelper(indent, queryParam, () => {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
else {
|
|
845
|
-
text += `${indent.get()}query_builder.set_pair("${queryParam.key}", ${queryParam.name}_vec.iter().map(|(k, v)| format!("{k},{v}")).collect::<Vec<String>>().join(","));\n`;
|
|
846
|
-
}
|
|
847
|
-
text += `${indent.pop().get()}}\n`;
|
|
848
|
-
return text;
|
|
951
|
+
const queryParamRef = qualifiedParamName(queryParam);
|
|
952
|
+
return (queryParam.explode)
|
|
953
|
+
? `${indent.get()}for (k, v) in ${queryParamRef}.iter() {\n`
|
|
954
|
+
+ `${indent.push().get()}query_builder.append_pair(k.as_str(), v.to_string());\n`
|
|
955
|
+
+ `${indent.pop().get()}}\n`
|
|
956
|
+
: `${indent.get()}let mut ${queryParam.name} = ${queryParamRef}.iter().collect::<Vec<_>>();\n`
|
|
957
|
+
+ `${indent.get()}${queryParam.name}.sort_by_key(|p| p.0);\n`
|
|
958
|
+
+ `${indent.get()}query_builder.set_pair("${queryParam.key}", ${queryParam.name}.iter().map(|(k, v)| format!("{k},{v}")).collect::<Vec<String>>().join(","));\n`;
|
|
849
959
|
});
|
|
850
960
|
}
|
|
851
961
|
else {
|
|
@@ -903,7 +1013,8 @@ function applyHeaderParams(indent, use, method, paramGroups, inClosure, requestV
|
|
|
903
1013
|
}
|
|
904
1014
|
body += getParamValueHelper(indent, headerParam, () => {
|
|
905
1015
|
if (headerParam.kind === 'headerHashMap') {
|
|
906
|
-
|
|
1016
|
+
const headerParamRef = qualifiedParamName(headerParam);
|
|
1017
|
+
let setter = `for (k, v) in ${headerParamRef} {\n`;
|
|
907
1018
|
setter += `${indent.push().get()}${requestVarName}.insert_header(format!("${headerParam.header}-{k}"), v);\n`;
|
|
908
1019
|
setter += `${indent.pop().get()}}\n`;
|
|
909
1020
|
return setter;
|
|
@@ -961,15 +1072,15 @@ function constructRequest(indent, use, method, paramGroups, inClosure, urlVarNam
|
|
|
961
1072
|
const requestContentType = paramGroups.partialBody[0].type;
|
|
962
1073
|
use.addForType(requestContentType);
|
|
963
1074
|
if (inClosure) {
|
|
964
|
-
body += `${indent.get()}let body: Result<${helpers.getTypeDeclaration(requestContentType)}> = ${requestContentType.content.
|
|
1075
|
+
body += `${indent.get()}let body: Result<${helpers.getTypeDeclaration(requestContentType)}> = ${requestContentType.content.name} {\n`;
|
|
965
1076
|
}
|
|
966
1077
|
else {
|
|
967
|
-
body += `${indent.get()}let body: ${helpers.getTypeDeclaration(requestContentType)} = ${requestContentType.content.
|
|
1078
|
+
body += `${indent.get()}let body: ${helpers.getTypeDeclaration(requestContentType)} = ${requestContentType.content.name} {\n`;
|
|
968
1079
|
}
|
|
969
1080
|
indent.push();
|
|
970
1081
|
for (const partialBodyParam of paramGroups.partialBody) {
|
|
971
|
-
if (partialBodyParam.type.content
|
|
972
|
-
throw new CodegenError('InternalError', `spread param ${partialBodyParam.name} has conflicting model type ${partialBodyParam.type.content.
|
|
1082
|
+
if (partialBodyParam.type.content !== requestContentType.content) {
|
|
1083
|
+
throw new CodegenError('InternalError', `spread param ${partialBodyParam.name} has conflicting model type ${partialBodyParam.type.content.name}, expected model type ${requestContentType.content.name}`);
|
|
973
1084
|
}
|
|
974
1085
|
if (partialBodyParam.optional) {
|
|
975
1086
|
body += `${indent.get()}${partialBodyParam.name}: options.${partialBodyParam.name}${inClosure ? '.clone()' : ''},\n`;
|
|
@@ -979,7 +1090,7 @@ function constructRequest(indent, use, method, paramGroups, inClosure, urlVarNam
|
|
|
979
1090
|
if (inClosure) {
|
|
980
1091
|
initializer = initializer + '.clone()';
|
|
981
1092
|
}
|
|
982
|
-
if (requestContentType.content.
|
|
1093
|
+
if (requestContentType.content.visibility === 'pub') {
|
|
983
1094
|
// spread param maps to a non-internal model, so it must be wrapped in Some()
|
|
984
1095
|
initializer = `Some(${initializer})`;
|
|
985
1096
|
}
|
|
@@ -1062,8 +1173,9 @@ function emitEmptyPathParamCheck(indent, param) {
|
|
|
1062
1173
|
// no length to check so bail
|
|
1063
1174
|
return '';
|
|
1064
1175
|
}
|
|
1176
|
+
const paramRef = qualifiedParamName(param);
|
|
1065
1177
|
return helpers.buildIfBlock(indent, {
|
|
1066
|
-
condition: `${
|
|
1178
|
+
condition: `${paramRef}${toString}.is_empty()`,
|
|
1067
1179
|
body: (indent) => `${indent.get()}return Err(azure_core::Error::with_message(azure_core::error::ErrorKind::Other, "parameter ${param.name} cannot be empty"));\n`,
|
|
1068
1180
|
});
|
|
1069
1181
|
}
|
|
@@ -1647,6 +1759,9 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
|
|
|
1647
1759
|
else if (overrideParamName) {
|
|
1648
1760
|
paramName = overrideParamName;
|
|
1649
1761
|
}
|
|
1762
|
+
else if (param.group) {
|
|
1763
|
+
paramName = qualifiedParamName(param);
|
|
1764
|
+
}
|
|
1650
1765
|
const encodeBytes = function (type, param) {
|
|
1651
1766
|
const encoding = helpers.getBytesEncodingMethod(type.encoding, 'encode', use);
|
|
1652
1767
|
if (param) {
|
|
@@ -1675,6 +1790,7 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
|
|
|
1675
1790
|
// contains the result from calculating if the
|
|
1676
1791
|
// param requires borrowing.
|
|
1677
1792
|
let mustBorrow = !helpers.isQueryParameter(param);
|
|
1793
|
+
const isGrouped = !!param.group;
|
|
1678
1794
|
const paramType = helpers.unwrapType(param.type);
|
|
1679
1795
|
// we want multi to hit the else case so the necessary conversions etc can happen
|
|
1680
1796
|
if ((param.kind === 'headerCollection' || param.kind === 'queryCollection') && param.format !== 'multi') {
|
|
@@ -1701,8 +1817,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
|
|
|
1701
1817
|
switch (paramType.kind) {
|
|
1702
1818
|
case 'String':
|
|
1703
1819
|
paramValue = paramName;
|
|
1704
|
-
// if the param is on the client, then we must borrow
|
|
1705
|
-
mustBorrow = param.location === 'client' && fromSelf;
|
|
1820
|
+
// if the param is on the client or in a group struct, then we must borrow
|
|
1821
|
+
mustBorrow = isGrouped || (param.location === 'client' && fromSelf);
|
|
1706
1822
|
break;
|
|
1707
1823
|
case 'str':
|
|
1708
1824
|
paramValue = paramName;
|
|
@@ -1746,8 +1862,8 @@ function getHeaderPathQueryParamValue(use, param, fromSelf, neverBorrow, overrid
|
|
|
1746
1862
|
case 'headerHashMap':
|
|
1747
1863
|
case 'headerScalar':
|
|
1748
1864
|
// for non-copyable params (e.g. String), we need to borrow them if they're on the
|
|
1749
|
-
// client or we're in a closure and the param is required (header params are always owned)
|
|
1750
|
-
mustBorrow = nonCopyableType(param.type) && (param.location === 'client' || (!fromSelf && !param.optional));
|
|
1865
|
+
// client, in a group struct, or we're in a closure and the param is required (header params are always owned)
|
|
1866
|
+
mustBorrow = nonCopyableType(param.type) && (isGrouped || param.location === 'client' || (!fromSelf && !param.optional));
|
|
1751
1867
|
break;
|
|
1752
1868
|
}
|
|
1753
1869
|
return `${mustBorrow && !neverBorrow ? '&' : ''}${paramValue}`;
|
|
@@ -1823,4 +1939,8 @@ function isEnumString(type) {
|
|
|
1823
1939
|
const unwrapped = helpers.unwrapType(type);
|
|
1824
1940
|
return unwrapped.kind === 'enum' && unwrapped.type === 'String';
|
|
1825
1941
|
}
|
|
1942
|
+
/** returns the qualified name for a param, prefixing with the group name when the param belongs to a parameter group */
|
|
1943
|
+
function qualifiedParamName(param) {
|
|
1944
|
+
return param.group ? `${param.group.name}.${param.name}` : param.name;
|
|
1945
|
+
}
|
|
1826
1946
|
//# sourceMappingURL=clients.js.map
|