@azure-tools/typespec-ts 0.48.0-alpha.20260123.1 → 0.48.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-tools/typespec-ts",
3
- "version": "0.48.0-alpha.20260123.1",
3
+ "version": "0.48.1",
4
4
  "description": "An experimental TypeSpec emitter for TypeScript RLC",
5
5
  "main": "dist/src/index.js",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
22
22
  "@typespec/spector": "0.1.0-alpha.23-dev.0",
23
23
  "@typespec/spec-api": "0.1.0-alpha.13-dev.0",
24
24
  "@typespec/tspd": "0.73.3",
25
- "@azure-tools/azure-http-specs": "0.1.0-alpha.35-dev.9",
25
+ "@azure-tools/azure-http-specs": "0.1.0-alpha.37-dev.0",
26
26
  "@azure-tools/typespec-autorest": "^0.64.0",
27
27
  "@azure-tools/typespec-azure-core": "^0.64.0",
28
28
  "@azure-tools/typespec-azure-resource-manager": "^0.64.0",
@@ -73,7 +73,7 @@
73
73
  "@typespec/xml": "^0.78.0"
74
74
  },
75
75
  "dependencies": {
76
- "@azure-tools/rlc-common": "0.48.0-alpha.20260123.1",
76
+ "@azure-tools/rlc-common": "^0.48.1",
77
77
  "fast-xml-parser": "^4.5.0",
78
78
  "fs-extra": "^11.1.0",
79
79
  "lodash": "^4.17.21",
@@ -11,7 +11,8 @@ import {
11
11
  getOperationFunction,
12
12
  getOperationOptionsName,
13
13
  getSendPrivateFunction,
14
- isLroOnlyOperation
14
+ isLroOnlyOperation,
15
+ isLroAndPagingOperation
15
16
  } from "./helpers/operationHelpers.js";
16
17
 
17
18
  import { OperationPathAndDeserDetails } from "./interfaces.js";
@@ -174,7 +175,7 @@ export function buildOperationOptions(
174
175
  hasQuestionToken: boolean;
175
176
  docs: string[];
176
177
  }[] = [];
177
- if (isLroOnlyOperation(operation)) {
178
+ if (isLroOnlyOperation(operation) || isLroAndPagingOperation(operation)) {
178
179
  additionalOptions.push(lroOptions);
179
180
  }
180
181
  if (isDualFormat) {
@@ -169,16 +169,15 @@ export function getDeserializePrivateFunction(
169
169
  type: PathUncheckedResponseReference
170
170
  }
171
171
  ];
172
- // TODO: Support LRO + paging operation
173
- // https://github.com/Azure/autorest.typescript/issues/2313
174
172
  const isLroOnly = isLroOnlyOperation(operation);
173
+ const isLroAndPaging = isLroAndPagingOperation(operation);
175
174
 
176
175
  // TODO: Support operation overloads
177
176
  // TODO: Support multiple responses
178
177
  const response = operation.response;
179
178
  const restResponse = operation.operation.responses[0];
180
179
  let returnType;
181
- if (isLroOnly) {
180
+ if (isLroOnly || isLroAndPaging) {
182
181
  returnType = buildLroReturnType(context, operation);
183
182
  } else if (response.type && restResponse) {
184
183
  returnType = {
@@ -209,11 +208,12 @@ export function getDeserializePrivateFunction(
209
208
  `${getExceptionThrowStatement(context, operation)}`,
210
209
  "}"
211
210
  );
212
- const deserializedType = isLroOnly
213
- ? operation?.lroMetadata?.finalResponse?.result
214
- : restResponse
215
- ? restResponse.type
216
- : response.type;
211
+ const deserializedType =
212
+ isLroOnly || isLroAndPaging
213
+ ? operation?.lroMetadata?.finalResponse?.result
214
+ : restResponse
215
+ ? restResponse.type
216
+ : response.type;
217
217
  const lroSubSegments = isLroOnly
218
218
  ? operation?.lroMetadata?.finalResponse?.resultSegments
219
219
  : undefined;
@@ -575,8 +575,13 @@ export function getOperationFunction(
575
575
  optionalParamName
576
576
  );
577
577
  } else if (isLroAndPagingOperation(operation)) {
578
- // Case 3: both paging + lro operation is not supported yet so handle them as normal operation and customization may be needed
579
- // https://github.com/Azure/autorest.typescript/issues/2313
578
+ // Case 3: both paging + lro operation
579
+ return getLroAndPagingOperationFunction(
580
+ context,
581
+ [method[0], operation],
582
+ clientType,
583
+ optionalParamName
584
+ );
580
585
  }
581
586
 
582
587
  // TODO: Support operation overloads
@@ -704,9 +709,99 @@ function getLroOnlyOperationFunction(
704
709
  } as FunctionDeclarationStructure & { propertyName?: string };
705
710
  }
706
711
 
712
+ function getLroAndPagingOperationFunction(
713
+ context: SdkContext,
714
+ method: [string[], SdkLroPagingServiceMethod<SdkHttpOperation>],
715
+ clientType: string,
716
+ optionalParamName: string = "options"
717
+ ): FunctionDeclarationStructure & { propertyName?: string } {
718
+ const operation = method[1];
719
+ const parameters = getOperationSignatureParameters(
720
+ context,
721
+ method,
722
+ clientType
723
+ );
724
+ const { name, fixme = [] } = getOperationName(operation);
725
+
726
+ const returnType = buildLroPagingReturnType(context, operation);
727
+
728
+ // Build paging options from metadata
729
+ const pagingOptions = [
730
+ operation.response.resultSegments &&
731
+ `itemName: "${operation.response.resultSegments.map((p) => p.name).join(".")}"`,
732
+ operation.pagingMetadata.nextLinkSegments &&
733
+ `nextLinkName: "${operation.pagingMetadata.nextLinkSegments.map((p) => p.name).join(".")}"`,
734
+ operation.pagingMetadata.nextLinkVerb !== "GET" &&
735
+ `nextLinkMethod: "${operation.pagingMetadata.nextLinkVerb}"`
736
+ ].filter(Boolean);
737
+
738
+ // Build LRO resource location config
739
+ const allowedLocations = [
740
+ "azure-async-operation",
741
+ "location",
742
+ "original-uri",
743
+ "operation-location"
744
+ ];
745
+ const resourceLocationConfig =
746
+ operation.lroMetadata?.finalStateVia &&
747
+ allowedLocations.includes(operation.lroMetadata.finalStateVia)
748
+ ? `resourceLocationConfig: "${operation.lroMetadata.finalStateVia}"`
749
+ : "";
750
+
751
+ // Resolve references
752
+ const refs = {
753
+ pagedIterator: resolveReference(PagingHelpers.PagedAsyncIterableIterator),
754
+ buildPaging: resolveReference(PagingHelpers.BuildPagedAsyncIterator),
755
+ getLroPoller: resolveReference(PollingHelpers.GetLongRunningPoller),
756
+ pollerLike: resolveReference(AzurePollingDependencies.PollerLike),
757
+ operationState: resolveReference(AzurePollingDependencies.OperationState),
758
+ pathResponse: resolveReference(useDependencies().PathUncheckedResponse)
759
+ };
760
+
761
+ const expectedStatuses = getExpectedStatuses(operation);
762
+ const paramList = parameters.map((p) => p.name).join(", ");
763
+ const pagingOptionsStr =
764
+ pagingOptions.length > 0 ? `,\n {${pagingOptions.join(", ")}}` : "";
765
+
766
+ return {
767
+ kind: StructureKind.Function,
768
+ docs: [
769
+ ...getDocsFromDescription(operation.doc),
770
+ ...getFixmeForMultilineDocs(fixme)
771
+ ],
772
+ isAsync: false,
773
+ isExported: true,
774
+ name,
775
+ propertyName: normalizeName(operation.name, NameType.Property),
776
+ parameters,
777
+ returnType: `${refs.pagedIterator}<${returnType.type}>`,
778
+ statements: [
779
+ `
780
+ const initialPagingPoller = ${refs.getLroPoller}(context,
781
+ async (result: ${refs.pathResponse}) => result,
782
+ ${expectedStatuses}, {
783
+ updateIntervalInMs: ${optionalParamName}?.updateIntervalInMs,
784
+ abortSignal: ${optionalParamName}?.abortSignal,
785
+ getInitialResponse: () => _${name}Send(${paramList}),
786
+ ${resourceLocationConfig}
787
+ }) as ${refs.pollerLike}<${refs.operationState}<${refs.pathResponse}>, ${refs.pathResponse}>;
788
+
789
+ return ${refs.buildPaging}(
790
+ context,
791
+ async () => await initialPagingPoller,
792
+ _${name}Deserialize,
793
+ ${expectedStatuses}${pagingOptionsStr}
794
+ );
795
+ `
796
+ ]
797
+ };
798
+ }
799
+
707
800
  function buildLroReturnType(
708
801
  context: SdkContext,
709
- operation: SdkLroServiceMethod<SdkHttpOperation>
802
+ operation:
803
+ | SdkLroServiceMethod<SdkHttpOperation>
804
+ | SdkLroPagingServiceMethod<SdkHttpOperation>
710
805
  ) {
711
806
  const metadata = operation.lroMetadata;
712
807
  if (metadata !== undefined && metadata.finalResponse !== undefined) {
@@ -719,6 +814,19 @@ function buildLroReturnType(
719
814
  return { name: "", type: "void" };
720
815
  }
721
816
 
817
+ function buildLroPagingReturnType(
818
+ context: SdkContext,
819
+ operation: SdkLroPagingServiceMethod<SdkHttpOperation>
820
+ ) {
821
+ if (operation.response.type?.kind === "array") {
822
+ return {
823
+ name: (operation.response.type.valueType as any).name ?? "",
824
+ type: getTypeExpression(context, operation.response.type.valueType)
825
+ };
826
+ }
827
+ return { name: "", type: "void" };
828
+ }
829
+
722
830
  function getPagingOnlyOperationFunction(
723
831
  context: SdkContext,
724
832
  method: [string[], SdkPagingServiceMethod<SdkHttpOperation>],
@@ -1964,7 +2072,10 @@ export function getPropertyFullName(
1964
2072
  export function getExpectedStatuses(operation: ServiceOperation): string {
1965
2073
  let statusCodes = operation.operation.responses.map((x) => x.statusCodes);
1966
2074
  // LROs may call the same path but with GET to get the operation status.
1967
- if (isLroOnlyOperation(operation) && operation.operation.verb !== "get") {
2075
+ if (
2076
+ (isLroOnlyOperation(operation) || isLroAndPagingOperation(operation)) &&
2077
+ operation.operation.verb !== "get"
2078
+ ) {
1968
2079
  // DELETE: Add 200, 202 for polling
1969
2080
  // POST/PUT/PATCH: Add 200, 201, 202 for polling
1970
2081
  const verb = operation.operation.verb.toLowerCase();