@azure-tools/typespec-rust 0.41.5 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +39 -0
  2. package/dist/src/codegen/cargotoml.d.ts.map +1 -1
  3. package/dist/src/codegen/cargotoml.js +13 -3
  4. package/dist/src/codegen/cargotoml.js.map +1 -1
  5. package/dist/src/codegen/clients.d.ts.map +1 -1
  6. package/dist/src/codegen/clients.js +84 -186
  7. package/dist/src/codegen/clients.js.map +1 -1
  8. package/dist/src/codegen/codeGenerator.d.ts.map +1 -1
  9. package/dist/src/codegen/codeGenerator.js +8 -2
  10. package/dist/src/codegen/codeGenerator.js.map +1 -1
  11. package/dist/src/codegen/context.d.ts.map +1 -1
  12. package/dist/src/codegen/context.js +3 -2
  13. package/dist/src/codegen/context.js.map +1 -1
  14. package/dist/src/codegen/errors.d.ts.map +1 -1
  15. package/dist/src/codegen/fakes.d.ts +11 -0
  16. package/dist/src/codegen/fakes.d.ts.map +1 -0
  17. package/dist/src/codegen/fakes.js +431 -0
  18. package/dist/src/codegen/fakes.js.map +1 -0
  19. package/dist/src/codegen/headerTraits.js.map +1 -1
  20. package/dist/src/codegen/helpers.d.ts +3 -1
  21. package/dist/src/codegen/helpers.d.ts.map +1 -1
  22. package/dist/src/codegen/helpers.js.map +1 -1
  23. package/dist/src/codegen/mod.d.ts +3 -1
  24. package/dist/src/codegen/mod.d.ts.map +1 -1
  25. package/dist/src/codegen/mod.js +11 -5
  26. package/dist/src/codegen/mod.js.map +1 -1
  27. package/dist/src/codegen/models.js +3 -5
  28. package/dist/src/codegen/models.js.map +1 -1
  29. package/dist/src/codegen/parameters.d.ts +13 -0
  30. package/dist/src/codegen/parameters.d.ts.map +1 -0
  31. package/dist/src/codegen/parameters.js +64 -0
  32. package/dist/src/codegen/parameters.js.map +1 -0
  33. package/dist/src/codegen/use.d.ts.map +1 -1
  34. package/dist/src/codegen/use.js.map +1 -1
  35. package/dist/src/codemodel/client.d.ts +12 -0
  36. package/dist/src/codemodel/client.d.ts.map +1 -1
  37. package/dist/src/codemodel/client.js +1 -0
  38. package/dist/src/codemodel/client.js.map +1 -1
  39. package/dist/src/codemodel/crate.d.ts +2 -0
  40. package/dist/src/codemodel/crate.d.ts.map +1 -1
  41. package/dist/src/codemodel/crate.js +1 -0
  42. package/dist/src/codemodel/crate.js.map +1 -1
  43. package/dist/src/codemodel/customizations.d.ts.map +1 -1
  44. package/dist/src/codemodel/method.d.ts.map +1 -1
  45. package/dist/src/codemodel/types.d.ts.map +1 -1
  46. package/dist/src/codemodel/types.js +1 -1
  47. package/dist/src/codemodel/types.js.map +1 -1
  48. package/dist/src/lib.d.ts +2 -0
  49. package/dist/src/lib.d.ts.map +1 -1
  50. package/dist/src/lib.js +6 -0
  51. package/dist/src/lib.js.map +1 -1
  52. package/dist/src/tcgcadapter/adapter.d.ts +8 -0
  53. package/dist/src/tcgcadapter/adapter.d.ts.map +1 -1
  54. package/dist/src/tcgcadapter/adapter.js +137 -53
  55. package/dist/src/tcgcadapter/adapter.js.map +1 -1
  56. package/dist/src/utils/utils.js.map +1 -1
  57. package/package.json +36 -36
@@ -90,11 +90,17 @@ export class Adapter {
90
90
  serviceType = 'azure-arm';
91
91
  }
92
92
  this.crate = new rust.Crate(this.options['crate-name'], (_a = this.options['crate-version']) !== null && _a !== void 0 ? _a : '0.1.0', serviceType);
93
+ this.crate.generateFakes = this.options['generate-fakes'] === true;
93
94
  }
94
95
  /** performs all the steps to convert tcgc to a crate */
95
96
  tcgcToCrate() {
96
97
  this.adaptTypes();
97
98
  this.adaptClients();
99
+ // Register before CodeGenerator sorts dependencies, including nested clients.
100
+ const hasClients = (module) => module.clients.length > 0 || module.subModules.some(hasClients);
101
+ if (this.crate.generateFakes && hasClients(this.crate)) {
102
+ this.crate.addDependency(new rust.CrateDependency('async-trait'));
103
+ }
98
104
  return this.crate;
99
105
  }
100
106
  /** converts tcgc docs to formatted rust.Docs */
@@ -269,7 +275,8 @@ export class Adapter {
269
275
  * @returns a Rust enum
270
276
  */
271
277
  getEnum(sdkEnum) {
272
- var _a, _b, _c;
278
+ var _a, _b;
279
+ var _c;
273
280
  const enumName = utils.deconstruct(sdkEnum.name).map((each) => utils.capitalize(each)).join('');
274
281
  let rustEnum = this.types.get(enumName);
275
282
  if (rustEnum) {
@@ -485,7 +492,8 @@ export class Adapter {
485
492
  * @returns a Rust union
486
493
  */
487
494
  getDiscriminatedUnion(src) {
488
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
495
+ var _a, _b, _c, _d, _e, _f, _g, _h;
496
+ var _j;
489
497
  if (src.name.length === 0) {
490
498
  throw new AdapterError('InternalError', 'unnamed union', (_a = src.__raw) === null || _a === void 0 ? void 0 : _a.node);
491
499
  }
@@ -547,9 +555,9 @@ export class Adapter {
547
555
  rustUnion.unionKind = new rust.DiscriminatedUnionBase(baseModel);
548
556
  }
549
557
  // we need to handle the case where src is a root with no child types
550
- for (const subType of Object.values((_e = src.discriminatedSubtypes) !== null && _e !== void 0 ? _e : {})) {
558
+ for (const subType of Object.values((_j = src.discriminatedSubtypes) !== null && _j !== void 0 ? _j : {})) {
551
559
  if (!subType.discriminatorValue) {
552
- throw new AdapterError('InternalError', `model ${subType.name} has no discriminator value`, (_f = subType.__raw) === null || _f === void 0 ? void 0 : _f.node);
560
+ throw new AdapterError('InternalError', `model ${subType.name} has no discriminator value`, (_e = subType.__raw) === null || _e === void 0 ? void 0 : _e.node);
553
561
  }
554
562
  const unionMemberType = subType.discriminatedSubtypes ? this.getDiscriminatedUnion(subType) : this.getModel(subType);
555
563
  const rustUnionMember = new rust.DiscriminatedUnionMember(unionMemberType, subType.discriminatorValue);
@@ -562,7 +570,7 @@ export class Adapter {
562
570
  // we should have verified this earlier.
563
571
  // having this check means the compiler won't bark
564
572
  // at us when accessing src.discriminatedOptions
565
- throw new AdapterError('InternalError', 'getDiscriminatedUnion called for non-discriminated union', (_g = src.__raw) === null || _g === void 0 ? void 0 : _g.node);
573
+ throw new AdapterError('InternalError', 'getDiscriminatedUnion called for non-discriminated union', (_f = src.__raw) === null || _f === void 0 ? void 0 : _f.node);
566
574
  }
567
575
  rustUnion = new rust.DiscriminatedUnion(unionName, adaptAccessFlags(src.access), src.discriminatedOptions.discriminatorPropertyName, this.adaptNamespace(src.namespace));
568
576
  if (src.discriminatedOptions.envelopePropertyName) {
@@ -585,12 +593,12 @@ export class Adapter {
585
593
  // END WORKAROUND
586
594
  for (const unionMember of src.variantTypes) {
587
595
  if (unionMember.kind !== 'model') {
588
- throw new AdapterError('UnsupportedTsp', `non-model union member kind ${unionMember.kind}`, (_h = unionMember.__raw) === null || _h === void 0 ? void 0 : _h.node);
596
+ throw new AdapterError('UnsupportedTsp', `non-model union member kind ${unionMember.kind}`, (_g = unionMember.__raw) === null || _g === void 0 ? void 0 : _g.node);
589
597
  }
590
598
  // TODO: use unionMember.discriminatorValue
591
599
  const discriminatorValue = discriminatorValues.get(unionMember.name);
592
600
  if (!discriminatorValue) {
593
- throw new AdapterError('InternalError', `didn't find discriminant value for type ${unionMember.name}`, (_j = unionMember.__raw) === null || _j === void 0 ? void 0 : _j.node);
601
+ throw new AdapterError('InternalError', `didn't find discriminant value for type ${unionMember.name}`, (_h = unionMember.__raw) === null || _h === void 0 ? void 0 : _h.node);
594
602
  }
595
603
  const unionMemberType = this.getModel(unionMember);
596
604
  const rustUnionMember = new rust.DiscriminatedUnionMember(unionMemberType, discriminatorValue);
@@ -605,8 +613,9 @@ export class Adapter {
605
613
  return rustUnion;
606
614
  }
607
615
  getSerializedPropertyName(property) {
608
- var _a, _b, _c, _d, _e;
609
- return property.kind === 'property' ? (_d = (_b = (_a = property.serializationOptions.json) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : (_c = property.serializationOptions.xml) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : (_e = property.serializationOptions.multipart) === null || _e === void 0 ? void 0 : _e.name : undefined;
616
+ var _a, _b, _c;
617
+ var _d, _e;
618
+ return property.kind === 'property' ? (_e = (_d = (_a = property.serializationOptions.json) === null || _a === void 0 ? void 0 : _a.name) !== null && _d !== void 0 ? _d : (_b = property.serializationOptions.xml) === null || _b === void 0 ? void 0 : _b.name) !== null && _e !== void 0 ? _e : (_c = property.serializationOptions.multipart) === null || _c === void 0 ? void 0 : _c.name : undefined;
610
619
  }
611
620
  /**
612
621
  * converts a non-discriminated tcgc union to either a flat merged Rust Enum (union-of-enums)
@@ -805,7 +814,8 @@ export class Adapter {
805
814
  * @returns a Rust model field
806
815
  */
807
816
  getModelField(modelFlags, property, modelVisibility, stack) {
808
- var _a, _b, _c, _d, _e, _f, _g;
817
+ var _a, _b, _c;
818
+ var _d, _e, _f, _g;
809
819
  const fieldNeedsBoxing = function (fieldType) {
810
820
  if (fieldType.kind === 'model' && (stack.includes(fieldType))) {
811
821
  // if the field's type is a model and it's in the type stack then
@@ -834,7 +844,7 @@ export class Adapter {
834
844
  if (notSpreadOnly || property.optional) {
835
845
  fieldType = this.getOptionType(fieldType.kind === 'box' ? fieldType : this.typeToWireType(fieldType));
836
846
  }
837
- const serializedName = (_a = this.getSerializedPropertyName(property)) !== null && _a !== void 0 ? _a : property.name;
847
+ const serializedName = (_d = this.getSerializedPropertyName(property)) !== null && _d !== void 0 ? _d : property.name;
838
848
  const modelField = new rust.ModelField(naming.getEscapedReservedName(utils.snakeCaseName(property.name), 'prop'), serializedName, modelVisibility, fieldType, property.optional);
839
849
  modelField.docs = this.adaptDocs(property.summary, property.doc);
840
850
  // append visibility info as a doc comment when visibility is restricted
@@ -901,7 +911,7 @@ export class Adapter {
901
911
  code: 'DuplicateClientOption',
902
912
  severity: 'warning',
903
913
  message: `duplicate client option ${optionName} on model field ${property.name} will be ignored`,
904
- target: (_c = (_b = property.__raw) === null || _b === void 0 ? void 0 : _b.node) !== null && _c !== void 0 ? _c : tsp.NoTarget,
914
+ target: (_e = (_a = property.__raw) === null || _a === void 0 ? void 0 : _a.node) !== null && _e !== void 0 ? _e : tsp.NoTarget,
905
915
  });
906
916
  continue;
907
917
  }
@@ -914,7 +924,7 @@ export class Adapter {
914
924
  code: 'DuplicateClientOption',
915
925
  severity: 'warning',
916
926
  message: `duplicate client option ${optionName} on model field ${property.name} will be ignored`,
917
- target: (_e = (_d = property.__raw) === null || _d === void 0 ? void 0 : _d.node) !== null && _e !== void 0 ? _e : tsp.NoTarget,
927
+ target: (_f = (_b = property.__raw) === null || _b === void 0 ? void 0 : _b.node) !== null && _f !== void 0 ? _f : tsp.NoTarget,
918
928
  });
919
929
  continue;
920
930
  }
@@ -925,7 +935,7 @@ export class Adapter {
925
935
  code: 'InvalidClientOption',
926
936
  severity: 'warning',
927
937
  message: `invalid client option ${optionName} on model field ${property.name}`,
928
- target: (_g = (_f = property.__raw) === null || _f === void 0 ? void 0 : _f.node) !== null && _g !== void 0 ? _g : tsp.NoTarget,
938
+ target: (_g = (_c = property.__raw) === null || _c === void 0 ? void 0 : _c.node) !== null && _g !== void 0 ? _g : tsp.NoTarget,
929
939
  });
930
940
  }
931
941
  }
@@ -1343,7 +1353,8 @@ export class Adapter {
1343
1353
  * @returns a Rust client
1344
1354
  */
1345
1355
  recursiveAdaptClient(client, parent) {
1346
- var _a, _b, _c, _d, _e, _f, _g, _h;
1356
+ var _a, _b, _c, _d, _e, _f;
1357
+ var _g, _h;
1347
1358
  let clientName = client.name;
1348
1359
  // NOTE: if the client has the @clientName decorator applied then use that verbatim
1349
1360
  if (parent && !hasClientNameDecorator(client.decorators)) {
@@ -1416,7 +1427,8 @@ export class Adapter {
1416
1427
  * @returns the AuthTypes enum for the credential that was handled, or AuthTypes.Default if none were
1417
1428
  */
1418
1429
  const processCredential = (rustClient, param, cred, constructable) => {
1419
- var _a, _b;
1430
+ var _a;
1431
+ var _b;
1420
1432
  switch (cred.type) {
1421
1433
  case 'noAuth':
1422
1434
  return AuthTypes.NoAuth;
@@ -1439,7 +1451,7 @@ export class Adapter {
1439
1451
  return AuthTypes.WithAuth;
1440
1452
  }
1441
1453
  };
1442
- const ctorParams = new Array();
1454
+ const ctorParams = rustClient.constructable.parameters;
1443
1455
  for (const param of client.clientInitialization.parameters) {
1444
1456
  switch (param.kind) {
1445
1457
  case 'credential':
@@ -1512,6 +1524,10 @@ export class Adapter {
1512
1524
  break;
1513
1525
  }
1514
1526
  case 'method': {
1527
+ if (isRequiredFixedInput(param)) {
1528
+ // Operations serialize the constant directly, without stored client state.
1529
+ continue;
1530
+ }
1515
1531
  if (param.isApiVersionParam && param.optional && !param.clientDefaultValue) {
1516
1532
  if (!parent && client.children && client.methods.length === 0) {
1517
1533
  // this is the top-level client for a multi-client scenario.
@@ -1536,6 +1552,7 @@ export class Adapter {
1536
1552
  rustClient.constructable.constructors.push(ctorWithNoCredential);
1537
1553
  }
1538
1554
  // propagate ctor params to all client ctors
1555
+ helpers.sortClientParameters(ctorParams);
1539
1556
  for (const constructor of rustClient.constructable.constructors) {
1540
1557
  constructor.params.push(...ctorParams);
1541
1558
  // ensure param order of endpoint, credential, other
@@ -1548,6 +1565,9 @@ export class Adapter {
1548
1565
  // to create a child client that will need to inherit our client params.
1549
1566
  rustClient.endpoint = parent.endpoint;
1550
1567
  for (const prop of client.clientInitialization.parameters) {
1568
+ if (prop.kind === 'method' && isRequiredFixedInput(prop)) {
1569
+ continue;
1570
+ }
1551
1571
  const name = utils.snakeCaseName(prop.name);
1552
1572
  const parentField = parent.fields.find((v) => v.name === name);
1553
1573
  if (parentField) {
@@ -1581,6 +1601,7 @@ export class Adapter {
1581
1601
  const field = new rust.StructField(clientParam.name, 'pubCrate', clientParam.type);
1582
1602
  cur.fields.push(field);
1583
1603
  // propagate this param to all client constructors
1604
+ constructable.parameters.push(clientParam);
1584
1605
  for (const constructor of constructable.constructors) {
1585
1606
  constructor.params.push(clientParam);
1586
1607
  }
@@ -1593,7 +1614,7 @@ export class Adapter {
1593
1614
  else {
1594
1615
  throw new AdapterError('InternalError', `uninstantiatable client ${client.name} has no parent`);
1595
1616
  }
1596
- for (const child of (_f = client.children) !== null && _f !== void 0 ? _f : []) {
1617
+ for (const child of (_g = client.children) !== null && _g !== void 0 ? _g : []) {
1597
1618
  const subClient = this.recursiveAdaptClient(child, rustClient);
1598
1619
  this.adaptClientAccessor(client, child, rustClient, subClient);
1599
1620
  }
@@ -1605,7 +1626,7 @@ export class Adapter {
1605
1626
  code: 'LroPagingNotSupported',
1606
1627
  severity: 'warning',
1607
1628
  message: `skip emitting Paging LRO ${method.name}`,
1608
- target: (_h = (_g = method.__raw) === null || _g === void 0 ? void 0 : _g.node) !== null && _h !== void 0 ? _h : tsp.NoTarget,
1629
+ target: (_h = (_f = method.__raw) === null || _f === void 0 ? void 0 : _f.node) !== null && _h !== void 0 ? _h : tsp.NoTarget,
1609
1630
  });
1610
1631
  continue;
1611
1632
  }
@@ -1642,6 +1663,16 @@ export class Adapter {
1642
1663
  tokenCredParam.docs.summary = `An implementation of [\`TokenCredential\`](azure_core::credentials::TokenCredential) that can provide an Entra ID token to use when authenticating.`;
1643
1664
  ctorTokenCredential.params.push(tokenCredParam);
1644
1665
  ctorTokenCredential.docs.summary = `Creates a new ${rustClient.name}, using Entra ID authentication.`;
1666
+ if (this.crate.type === 'azure-arm') {
1667
+ ctorTokenCredential.docs.description = 'Public cloud is used when no cloud configuration is supplied. For a custom cloud,\n'
1668
+ + 'set [`CustomConfiguration::endpoint`](azure_core::cloud::CustomConfiguration::endpoint)\n'
1669
+ + 'and register its authentication audience using the shared\n'
1670
+ + '[`Audience`](azure_core::cloud::resource_manager::Audience) marker.\n'
1671
+ + "Configure the credential's cloud separately to use its identity authority.\n\n"
1672
+ + '# Errors\n\n'
1673
+ + 'Returns an error if a custom cloud has no endpoint or Resource Manager audience,\n'
1674
+ + 'or if its endpoint URL is invalid.';
1675
+ }
1645
1676
  return ctorTokenCredential;
1646
1677
  }
1647
1678
  /**
@@ -1695,6 +1726,9 @@ export class Adapter {
1695
1726
  const clientAccessor = new rust.ClientAccessor(`get_${utils.snakeCaseName(subClient.name)}`, rustClient, subClient);
1696
1727
  clientAccessor.docs.summary = `Returns a new instance of ${subClient.name}.`;
1697
1728
  for (const param of childClient.clientInitialization.parameters) {
1729
+ if (param.kind === 'method' && isRequiredFixedInput(param)) {
1730
+ continue;
1731
+ }
1698
1732
  // check if the client's initializer already has this parameter.
1699
1733
  // if it does then omit it from the method sig as we'll populate
1700
1734
  // the child client's value from the parent.
@@ -1721,7 +1755,8 @@ export class Adapter {
1721
1755
  * @param rustClient the client to which the method belongs
1722
1756
  */
1723
1757
  adaptMethod(method, rustClient) {
1724
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
1758
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
1759
+ var _y, _z;
1725
1760
  let srcMethodName = method.name;
1726
1761
  // NOTE: if the method has the @clientName decorator applied then skip fixing up the name
1727
1762
  if (!hasClientNameDecorator(method.decorators)) {
@@ -1738,7 +1773,7 @@ export class Adapter {
1738
1773
  code: 'PagingMethodRename',
1739
1774
  severity: 'warning',
1740
1775
  message: `renamed paging method from ${method.name} to ${srcMethodName}`,
1741
- target: (_b = (_a = method.__raw) === null || _a === void 0 ? void 0 : _a.node) !== null && _b !== void 0 ? _b : tsp.NoTarget,
1776
+ target: (_y = (_a = method.__raw) === null || _a === void 0 ? void 0 : _a.node) !== null && _y !== void 0 ? _y : tsp.NoTarget,
1742
1777
  });
1743
1778
  }
1744
1779
  else if ((method.kind === 'lro' || method.kind === 'lropaging') && !srcMethodName.match(/^begin/i)) {
@@ -1749,7 +1784,7 @@ export class Adapter {
1749
1784
  code: 'PollingMethodRename',
1750
1785
  severity: 'warning',
1751
1786
  message: `renamed polling method from ${method.name} to ${srcMethodName}`,
1752
- target: (_d = (_c = method.__raw) === null || _c === void 0 ? void 0 : _c.node) !== null && _d !== void 0 ? _d : tsp.NoTarget,
1787
+ target: (_z = (_b = method.__raw) === null || _b === void 0 ? void 0 : _b.node) !== null && _z !== void 0 ? _z : tsp.NoTarget,
1753
1788
  });
1754
1789
  }
1755
1790
  }
@@ -1760,7 +1795,7 @@ export class Adapter {
1760
1795
  // if the method was renamed then ensure it doesn't collide
1761
1796
  for (const existingMethod of rustClient.methods) {
1762
1797
  if (existingMethod.name === methodName) {
1763
- throw new AdapterError('NameCollision', `renamed method ${srcMethodName} collides with an existing method`, (_e = method.__raw) === null || _e === void 0 ? void 0 : _e.node);
1798
+ throw new AdapterError('NameCollision', `renamed method ${srcMethodName} collides with an existing method`, (_c = method.__raw) === null || _c === void 0 ? void 0 : _c.node);
1764
1799
  }
1765
1800
  }
1766
1801
  }
@@ -1814,28 +1849,31 @@ export class Adapter {
1814
1849
  lroFinalResultStrategy = new rust.LroFinalResultStrategyHeader('operation-location');
1815
1850
  break;
1816
1851
  case FinalStateValue.customLink:
1817
- if (((_f = method.lroMetadata.statusMonitorStep) === null || _f === void 0 ? void 0 : _f.kind) === "nextOperationLink") {
1852
+ if (((_d = method.lroMetadata.statusMonitorStep) === null || _d === void 0 ? void 0 : _d.kind) === "nextOperationLink") {
1818
1853
  const customHeaderName = method.lroMetadata.statusMonitorStep.target.property.name;
1819
1854
  if (customHeaderName.trim() === '') {
1820
- throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia === customLink && customHeaderName === "${customHeaderName}"`, (_g = method.__raw) === null || _g === void 0 ? void 0 : _g.node);
1855
+ throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia === customLink && customHeaderName === "${customHeaderName}"`, (_e = method.__raw) === null || _e === void 0 ? void 0 : _e.node);
1821
1856
  }
1822
1857
  lroFinalResultStrategy = new rust.LroFinalResultStrategyHeader(customHeaderName);
1823
1858
  }
1824
1859
  else {
1825
- throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia === customLink && lroMetadata.statusMonitorStep?.kind === "${(_h = method.lroMetadata.statusMonitorStep) === null || _h === void 0 ? void 0 : _h.kind}"`, (_j = method.__raw) === null || _j === void 0 ? void 0 : _j.node);
1860
+ throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia === customLink && lroMetadata.statusMonitorStep?.kind === "${(_f = method.lroMetadata.statusMonitorStep) === null || _f === void 0 ? void 0 : _f.kind}"`, (_g = method.__raw) === null || _g === void 0 ? void 0 : _g.node);
1826
1861
  }
1827
1862
  break;
1828
1863
  default:
1829
1864
  /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
1830
- throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia ${method.lroMetadata.finalStateVia} NYI`, (_k = method.__raw) === null || _k === void 0 ? void 0 : _k.node);
1865
+ throw new AdapterError('UnsupportedTsp', `lroMetadata.finalStateVia ${method.lroMetadata.finalStateVia} NYI`, (_h = method.__raw) === null || _h === void 0 ? void 0 : _h.node);
1831
1866
  }
1832
1867
  lroFinalResultStrategy.propertyName = method.lroMetadata.finalResultPath;
1833
1868
  }
1834
1869
  rustMethod = new rust.LroMethod(methodName, languageIndependentName, rustClient, pub, methodOptions, httpMethod, method.operation.path, lroFinalResultStrategy);
1870
+ if (this.crate.type === 'azure-arm') {
1871
+ rustMethod.resourceManagerFinalState = this.adaptResourceManagerFinalState(method);
1872
+ }
1835
1873
  }
1836
1874
  break;
1837
1875
  default:
1838
- throw new AdapterError('UnsupportedTsp', `method kind ${method.kind} NYI`, (_l = method.__raw) === null || _l === void 0 ? void 0 : _l.node);
1876
+ throw new AdapterError('UnsupportedTsp', `method kind ${method.kind} NYI`, (_j = method.__raw) === null || _j === void 0 ? void 0 : _j.node);
1839
1877
  }
1840
1878
  rustMethod.docs = this.adaptDocs(method.summary, method.doc);
1841
1879
  rustClient.methods.push(rustMethod);
@@ -1953,10 +1991,14 @@ export class Adapter {
1953
1991
  // cast is safe as we only need .type, .optional, .summary, .doc from it.
1954
1992
  const groupedParam = this.adaptMethodParameter(opParam, fieldProp, lifetime);
1955
1993
  const fieldOptional = fieldProp ? fieldProp.optional : opParam.optional;
1956
- if (!fieldOptional) {
1994
+ if (!fieldOptional && (groupedParam.type.kind === 'literal' || groupedParam.type.kind === 'enumValue')) {
1995
+ // Fixed wire values are still needed for requests, but are not caller inputs.
1996
+ processAdaptedParam(groupedParam, param);
1997
+ }
1998
+ else if (!fieldOptional) {
1957
1999
  if (!paramGroup) {
1958
2000
  if (param.type.kind !== 'model') {
1959
- throw new AdapterError('InternalError', `expected model type for parameter group but got ${param.type.kind}`, (_m = param.__raw) === null || _m === void 0 ? void 0 : _m.node);
2001
+ throw new AdapterError('InternalError', `expected model type for parameter group but got ${param.type.kind}`, (_k = param.__raw) === null || _k === void 0 ? void 0 : _k.node);
1960
2002
  }
1961
2003
  const groupName = utils.capitalize(param.type.name).replace(/\W/g, '');
1962
2004
  const paramName = naming.getEscapedReservedName(utils.snakeCaseName(param.name), 'param', reservedParams);
@@ -1986,22 +2028,21 @@ export class Adapter {
1986
2028
  for (const gp of groupedParams) {
1987
2029
  rustMethod.params.push(gp);
1988
2030
  }
1989
- // remove the group's model type from the module's models list.
1990
- // the parameter group struct will be emitted by the client codegen
1991
- // in method_options.rs. leaving the model in models.rs would create
1992
- // a duplicate struct definition with incompatible field types.
1993
- if (param.type.kind === 'model') {
1994
- const groupModelName = utils.capitalize(param.type.name).replace(/\W/g, '');
1995
- const ns = this.adaptNamespace(param.type.namespace);
1996
- const idx = ns.models.findIndex(m => m.kind === 'model' && m.name === groupModelName);
1997
- if (idx >= 0) {
1998
- ns.models.splice(idx, 1);
1999
- }
2031
+ }
2032
+ // Group-only models are emitted in method_options.rs or disappear.
2033
+ // Keep models also used in payloads, including through other models.
2034
+ if (param.type.kind === 'model'
2035
+ && (param.type.usage & (tcgc.UsageFlags.Json | tcgc.UsageFlags.Xml | tcgc.UsageFlags.Output | tcgc.UsageFlags.Spread | tcgc.UsageFlags.Exception)) === 0) {
2036
+ const groupModelName = utils.capitalize(param.type.name).replace(/\W/g, '');
2037
+ const ns = this.adaptNamespace(param.type.namespace);
2038
+ const idx = ns.models.findIndex(m => m.kind === 'model' && m.name === groupModelName);
2039
+ if (idx >= 0) {
2040
+ ns.models.splice(idx, 1);
2000
2041
  }
2001
2042
  }
2002
2043
  }
2003
2044
  else {
2004
- throw new AdapterError('InternalError', `didn't find operation parameter for method ${method.name} parameter ${param.name}`, (_o = param.__raw) === null || _o === void 0 ? void 0 : _o.node);
2045
+ throw new AdapterError('InternalError', `didn't find operation parameter for method ${method.name} parameter ${param.name}`, (_l = param.__raw) === null || _l === void 0 ? void 0 : _l.node);
2005
2046
  }
2006
2047
  }
2007
2048
  // client params aren't included in method.parameters so
@@ -2084,16 +2125,16 @@ export class Adapter {
2084
2125
  const responseFormat = getResponseFormat();
2085
2126
  if (method.kind === 'paging') {
2086
2127
  if (responseFormat !== 'JsonFormat' && responseFormat !== 'XmlFormat') {
2087
- throw new AdapterError('InternalError', `paged method ${method.name} unexpected response format ${responseFormat}`, (_p = method.__raw) === null || _p === void 0 ? void 0 : _p.node);
2128
+ throw new AdapterError('InternalError', `paged method ${method.name} unexpected response format ${responseFormat}`, (_m = method.__raw) === null || _m === void 0 ? void 0 : _m.node);
2088
2129
  }
2089
2130
  // for paged methods, tcgc models method.response.type as an Array<T>.
2090
2131
  // however, we want the synthesized paged response envelope type instead.
2091
2132
  const synthesizedType = method.operation.responses[0].type;
2092
2133
  if (!synthesizedType) {
2093
- throw new AdapterError('InternalError', `paged method ${method.name} has no synthesized response type`, (_q = method.__raw) === null || _q === void 0 ? void 0 : _q.node);
2134
+ throw new AdapterError('InternalError', `paged method ${method.name} has no synthesized response type`, (_o = method.__raw) === null || _o === void 0 ? void 0 : _o.node);
2094
2135
  }
2095
2136
  else if (synthesizedType.kind !== 'model') {
2096
- throw new AdapterError('UnsupportedTsp', `paged method ${method.name} synthesized response type has unexpected kind ${synthesizedType.kind}`, (_r = method.__raw) === null || _r === void 0 ? void 0 : _r.node);
2137
+ throw new AdapterError('UnsupportedTsp', `paged method ${method.name} synthesized response type has unexpected kind ${synthesizedType.kind}`, (_p = method.__raw) === null || _p === void 0 ? void 0 : _p.node);
2097
2138
  }
2098
2139
  const synthesizedModel = this.getModel(synthesizedType, new Array());
2099
2140
  const modelNs = this.adaptNamespace(synthesizedType.namespace);
@@ -2102,7 +2143,7 @@ export class Adapter {
2102
2143
  }
2103
2144
  // for the pager response type, remove the Option<T> around the Vec<T> for the page items
2104
2145
  if (!method.pagingMetadata.pageItemsSegments) {
2105
- throw new AdapterError('InternalError', `paged method ${method.name} has no pageItemsSegments`, (_s = method.__raw) === null || _s === void 0 ? void 0 : _s.node);
2146
+ throw new AdapterError('InternalError', `paged method ${method.name} has no pageItemsSegments`, (_q = method.__raw) === null || _q === void 0 ? void 0 : _q.node);
2106
2147
  }
2107
2148
  // unwrap all of the segments for the paged response
2108
2149
  let unwrappedCount = 0;
@@ -2113,13 +2154,13 @@ export class Adapter {
2113
2154
  switch (responseFormat) {
2114
2155
  case 'JsonFormat':
2115
2156
  if (segment.kind !== 'property' || !segment.serializationOptions.json) {
2116
- throw new AdapterError('InternalError', `paged method ${method.name} is missing JSON serialization data`, (_t = method.__raw) === null || _t === void 0 ? void 0 : _t.node);
2157
+ throw new AdapterError('InternalError', `paged method ${method.name} is missing JSON serialization data`, (_r = method.__raw) === null || _r === void 0 ? void 0 : _r.node);
2117
2158
  }
2118
2159
  serde = segment.serializationOptions.json.name;
2119
2160
  break;
2120
2161
  case 'XmlFormat':
2121
2162
  if (segment.kind !== 'property' || !segment.serializationOptions.xml) {
2122
- throw new AdapterError('InternalError', `paged method ${method.name} is missing XML serialization data`, (_u = method.__raw) === null || _u === void 0 ? void 0 : _u.node);
2163
+ throw new AdapterError('InternalError', `paged method ${method.name} is missing XML serialization data`, (_s = method.__raw) === null || _s === void 0 ? void 0 : _s.node);
2123
2164
  }
2124
2165
  serde = segment.serializationOptions.xml.name;
2125
2166
  break;
@@ -2145,14 +2186,14 @@ export class Adapter {
2145
2186
  }
2146
2187
  }
2147
2188
  if (unwrappedCount !== method.pagingMetadata.pageItemsSegments.length) {
2148
- throw new AdapterError('InternalError', `failed to unwrap paged items for method ${method.name}`, (_v = method.__raw) === null || _v === void 0 ? void 0 : _v.node);
2189
+ throw new AdapterError('InternalError', `failed to unwrap paged items for method ${method.name}`, (_t = method.__raw) === null || _t === void 0 ? void 0 : _t.node);
2149
2190
  }
2150
2191
  const pagedResponseType = new rust.Response(this.crate, synthesizedModel, responseFormat);
2151
2192
  // default to nextLink. will update it as required when we have that info
2152
2193
  const continuationKind = 'nextLink';
2153
2194
  // if the method has the forcePageIterator client option set to true,
2154
2195
  // expose this as a PageIterator so all items are accessible.
2155
- const forcePageIterator = (_w = method.decorators.find(d => d.name === 'Azure.ClientGenerator.Core.@clientOption' && d.arguments['name'] === 'forcePageIterator')) === null || _w === void 0 ? void 0 : _w.arguments['value'];
2196
+ const forcePageIterator = (_u = method.decorators.find(d => d.name === 'Azure.ClientGenerator.Core.@clientOption' && d.arguments['name'] === 'forcePageIterator')) === null || _u === void 0 ? void 0 : _u.arguments['value'];
2156
2197
  let resultType;
2157
2198
  if (forcePageIterator) {
2158
2199
  resultType = new rust.PageIterator(this.crate, pagedResponseType, continuationKind);
@@ -2190,7 +2231,7 @@ export class Adapter {
2190
2231
  const statusModel = this.getModel(method.lroMetadata.pollingInfo.responseModel, undefined, `${rustClient.name}${utils.pascalCase(rustMethod.name, false)}OperationStatus`);
2191
2232
  const statusType = this.typeToWireType(statusModel);
2192
2233
  if (statusType.kind !== 'model') {
2193
- throw new AdapterError('InternalError', `status type for an LRO method '${method.name}' is not a model`, (_x = method.__raw) === null || _x === void 0 ? void 0 : _x.node);
2234
+ throw new AdapterError('InternalError', `status type for an LRO method '${method.name}' is not a model`, (_v = method.__raw) === null || _v === void 0 ? void 0 : _v.node);
2194
2235
  }
2195
2236
  // the adapted type likely comes from core which means
2196
2237
  // it will be in the root namespace. since we emit these
@@ -2247,10 +2288,10 @@ export class Adapter {
2247
2288
  // can't do this until the method has been completely adapted
2248
2289
  const pageableMethod = rustMethod;
2249
2290
  pageableMethod.strategy = this.adaptPageableMethodStrategy(method, paramsMap, responseHeadersMap);
2250
- if (((_y = pageableMethod.strategy) === null || _y === void 0 ? void 0 : _y.kind) === 'nextLink') {
2291
+ if (((_w = pageableMethod.strategy) === null || _w === void 0 ? void 0 : _w.kind) === 'nextLink') {
2251
2292
  pageableMethod.strategy.reinjectedParams = this.adaptPageableMethodReinjectionParams(method, paramsMap);
2252
2293
  }
2253
- else if (((_z = pageableMethod.strategy) === null || _z === void 0 ? void 0 : _z.kind) === 'continuationToken') {
2294
+ else if (((_x = pageableMethod.strategy) === null || _x === void 0 ? void 0 : _x.kind) === 'continuationToken') {
2254
2295
  // set the continuation type to token on the Pager and the PagerOptions field in the method options
2255
2296
  pageableMethod.returns.type.continuation = 'token';
2256
2297
  for (const field of pageableMethod.options.type.type.fields) {
@@ -2261,6 +2302,46 @@ export class Adapter {
2261
2302
  }
2262
2303
  }
2263
2304
  }
2305
+ /**
2306
+ * Adapts an explicit final-response selector or inline result extraction for an ARM LRO.
2307
+ * Without either, the Resource Manager runtime selects the final response.
2308
+ *
2309
+ * @param method the LRO method to adapt
2310
+ * @returns the selector and serialized result path, or undefined for runtime defaults
2311
+ */
2312
+ adaptResourceManagerFinalState(method) {
2313
+ var _a, _b, _c;
2314
+ var _d;
2315
+ const metadata = method.lroMetadata;
2316
+ const selectors = new Map([
2317
+ [FinalStateValue.azureAsyncOperation, 'AzureAsyncOperation'],
2318
+ [FinalStateValue.location, 'Location'],
2319
+ [FinalStateValue.originalUri, 'OriginalUrl'],
2320
+ [FinalStateValue.operationLocation, 'OperationLocation'],
2321
+ ]);
2322
+ if (!selectors.has(metadata.finalStateVia)) {
2323
+ throw new AdapterError('UnsupportedTsp', `unsupported Resource Manager final-state selector ${metadata.finalStateVia}`);
2324
+ }
2325
+ const explicit = method.decorators.find(decorator => decorator.name === 'Azure.Core.@useFinalStateVia');
2326
+ const explicitFinalState = explicit === null || explicit === void 0 ? void 0 : explicit.arguments.finalState;
2327
+ if (explicitFinalState !== undefined && typeof explicitFinalState !== 'string') {
2328
+ throw new AdapterError('UnsupportedTsp', 'Resource Manager final-state selector must be a string');
2329
+ }
2330
+ // Inline results need an extraction callback even without an explicit selector.
2331
+ const finalState = explicitFinalState !== null && explicitFinalState !== void 0 ? explicitFinalState : (((_a = metadata.finalStep) === null || _a === void 0 ? void 0 : _a.kind) === 'pollingSuccessProperty' ? metadata.finalStateVia : undefined);
2332
+ if (finalState === undefined) {
2333
+ return undefined;
2334
+ }
2335
+ const selector = selectors.get(finalState);
2336
+ if (!selector) {
2337
+ throw new AdapterError('UnsupportedTsp', `unsupported Resource Manager final-state selector ${finalState}`);
2338
+ }
2339
+ return {
2340
+ selector,
2341
+ resultPath: selector === 'OperationLocation'
2342
+ ? (_d = (_c = (_b = metadata.finalResponse) === null || _b === void 0 ? void 0 : _b.resultSegments) === null || _c === void 0 ? void 0 : _c.map(segment => { var _a; return (_a = this.getSerializedPropertyName(segment)) !== null && _a !== void 0 ? _a : segment.name; })) !== null && _d !== void 0 ? _d : [] : [],
2343
+ };
2344
+ }
2264
2345
  /**
2265
2346
  * adapts response headers into Rust response headers and provides
2266
2347
  * a mapping from the tcgc response header to the Rust equivalent.
@@ -2842,6 +2923,9 @@ export class Adapter {
2842
2923
  }
2843
2924
  }
2844
2925
  }
2926
+ function isRequiredFixedInput(param) {
2927
+ return !param.optional && !param.isApiVersionParam && (param.type.kind === 'constant' || param.type.kind === 'enumvalue');
2928
+ }
2845
2929
  /** type guard to determine if type is a Ref<HashMap> */
2846
2930
  function isRefHashMap(type) {
2847
2931
  return utils.asTypeOf(type, 'hashmap', 'ref') !== undefined;