@azure-tools/typespec-ts 0.31.0 → 0.32.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 (169) hide show
  1. package/CHANGELOG.md +25 -7
  2. package/README.md +8 -0
  3. package/dist/src/contextManager.d.ts +2 -0
  4. package/dist/src/contextManager.d.ts.map +1 -1
  5. package/dist/src/contextManager.js.map +1 -1
  6. package/dist/src/framework/dependency.d.ts +69 -0
  7. package/dist/src/framework/dependency.d.ts.map +1 -0
  8. package/dist/src/framework/dependency.js +2 -0
  9. package/dist/src/framework/dependency.js.map +1 -0
  10. package/dist/src/framework/hooks/binder.d.ts +8 -2
  11. package/dist/src/framework/hooks/binder.d.ts.map +1 -1
  12. package/dist/src/framework/hooks/binder.js +107 -20
  13. package/dist/src/framework/hooks/binder.js.map +1 -1
  14. package/dist/src/framework/hooks/useDependencies.d.ts +4 -0
  15. package/dist/src/framework/hooks/useDependencies.d.ts.map +1 -0
  16. package/dist/src/framework/hooks/useDependencies.js +13 -0
  17. package/dist/src/framework/hooks/useDependencies.js.map +1 -0
  18. package/dist/src/framework/load-static-helpers.d.ts +16 -0
  19. package/dist/src/framework/load-static-helpers.d.ts.map +1 -0
  20. package/dist/src/framework/load-static-helpers.js +93 -0
  21. package/dist/src/framework/load-static-helpers.js.map +1 -0
  22. package/dist/src/framework/reference.d.ts +1 -1
  23. package/dist/src/framework/reference.d.ts.map +1 -1
  24. package/dist/src/framework/reference.js +16 -2
  25. package/dist/src/framework/reference.js.map +1 -1
  26. package/dist/src/framework/sample.js +1 -1
  27. package/dist/src/framework/sample.js.map +1 -1
  28. package/dist/src/index.d.ts +1 -1
  29. package/dist/src/index.d.ts.map +1 -1
  30. package/dist/src/index.js +113 -79
  31. package/dist/src/index.js.map +1 -1
  32. package/dist/src/lib.d.ts +10 -1
  33. package/dist/src/lib.d.ts.map +1 -1
  34. package/dist/src/lib.js +8 -1
  35. package/dist/src/lib.js.map +1 -1
  36. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  37. package/dist/src/modular/buildClassicalClient.js +12 -9
  38. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  39. package/dist/src/modular/buildClassicalOperationGroups.d.ts.map +1 -1
  40. package/dist/src/modular/buildClassicalOperationGroups.js +1 -11
  41. package/dist/src/modular/buildClassicalOperationGroups.js.map +1 -1
  42. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  43. package/dist/src/modular/buildClientContext.js +73 -52
  44. package/dist/src/modular/buildClientContext.js.map +1 -1
  45. package/dist/src/modular/buildCodeModel.d.ts +1 -1
  46. package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
  47. package/dist/src/modular/buildCodeModel.js +36 -62
  48. package/dist/src/modular/buildCodeModel.js.map +1 -1
  49. package/dist/src/modular/buildHelperSerializers.d.ts.map +1 -1
  50. package/dist/src/modular/buildHelperSerializers.js.map +1 -1
  51. package/dist/src/modular/buildOperations.d.ts +1 -3
  52. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  53. package/dist/src/modular/buildOperations.js +9 -69
  54. package/dist/src/modular/buildOperations.js.map +1 -1
  55. package/dist/src/modular/buildRestorePoller.d.ts +3 -0
  56. package/dist/src/modular/buildRestorePoller.d.ts.map +1 -0
  57. package/dist/src/modular/buildRestorePoller.js +203 -0
  58. package/dist/src/modular/buildRestorePoller.js.map +1 -0
  59. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  60. package/dist/src/modular/buildRootIndex.js +37 -0
  61. package/dist/src/modular/buildRootIndex.js.map +1 -1
  62. package/dist/src/modular/emitLoggerFile.d.ts +4 -0
  63. package/dist/src/modular/emitLoggerFile.d.ts.map +1 -0
  64. package/dist/src/modular/emitLoggerFile.js +16 -0
  65. package/dist/src/modular/emitLoggerFile.js.map +1 -0
  66. package/dist/src/modular/emitModels.d.ts.map +1 -1
  67. package/dist/src/modular/emitModels.js +0 -5
  68. package/dist/src/modular/emitModels.js.map +1 -1
  69. package/dist/src/modular/external-dependencies.d.ts +26 -0
  70. package/dist/src/modular/external-dependencies.d.ts.map +1 -0
  71. package/dist/src/modular/external-dependencies.js +137 -0
  72. package/dist/src/modular/external-dependencies.js.map +1 -0
  73. package/dist/src/modular/helpers/clientHelpers.d.ts +13 -6
  74. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  75. package/dist/src/modular/helpers/clientHelpers.js +92 -7
  76. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  77. package/dist/src/modular/helpers/operationHelpers.d.ts +6 -1
  78. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  79. package/dist/src/modular/helpers/operationHelpers.js +43 -69
  80. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  81. package/dist/src/modular/helpers/typeHelpers.d.ts +1 -0
  82. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  83. package/dist/src/modular/helpers/typeHelpers.js +6 -0
  84. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  85. package/dist/src/modular/interfaces.d.ts +1 -0
  86. package/dist/src/modular/interfaces.d.ts.map +1 -1
  87. package/dist/src/modular/serialization/buildSerializerFunction.d.ts.map +1 -1
  88. package/dist/src/modular/serialization/buildSerializerFunction.js +2 -20
  89. package/dist/src/modular/serialization/buildSerializerFunction.js.map +1 -1
  90. package/dist/src/modular/static-helpers-metadata.d.ts +72 -0
  91. package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -0
  92. package/dist/src/modular/static-helpers-metadata.js +72 -0
  93. package/dist/src/modular/static-helpers-metadata.js.map +1 -0
  94. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  95. package/dist/src/transform/transfromRLCOptions.js +56 -49
  96. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  97. package/dist/src/utils/credentialUtils.d.ts +10 -0
  98. package/dist/src/utils/credentialUtils.d.ts.map +1 -0
  99. package/dist/src/utils/credentialUtils.js +37 -0
  100. package/dist/src/utils/credentialUtils.js.map +1 -0
  101. package/dist/src/utils/dirname.d.ts +9 -0
  102. package/dist/src/utils/dirname.d.ts.map +1 -0
  103. package/dist/src/utils/dirname.js +12 -0
  104. package/dist/src/utils/dirname.js.map +1 -0
  105. package/dist/src/utils/emitUtil.d.ts.map +1 -1
  106. package/dist/src/utils/emitUtil.js +3 -5
  107. package/dist/src/utils/emitUtil.js.map +1 -1
  108. package/dist/src/utils/modelUtils.d.ts +1 -1
  109. package/dist/src/utils/modelUtils.js +3 -2
  110. package/dist/src/utils/modelUtils.js.map +1 -1
  111. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  112. package/dist/src/utils/operationUtil.js +20 -2
  113. package/dist/src/utils/operationUtil.js.map +1 -1
  114. package/dist/src/utils/resolve-project-root.d.ts +7 -0
  115. package/dist/src/utils/resolve-project-root.d.ts.map +1 -0
  116. package/dist/src/utils/resolve-project-root.js +22 -0
  117. package/dist/src/utils/resolve-project-root.js.map +1 -0
  118. package/dist/tsconfig.tsbuildinfo +1 -1
  119. package/package.json +29 -25
  120. package/src/contextManager.ts +2 -0
  121. package/src/framework/dependency.ts +56 -0
  122. package/src/framework/hooks/binder.ts +144 -27
  123. package/src/framework/hooks/useDependencies.ts +18 -0
  124. package/src/framework/load-static-helpers.ts +174 -0
  125. package/src/framework/reference.ts +27 -3
  126. package/src/framework/sample.ts +1 -1
  127. package/src/index.ts +154 -113
  128. package/src/lib.ts +8 -1
  129. package/src/modular/buildClassicalClient.ts +14 -12
  130. package/src/modular/buildClassicalOperationGroups.ts +1 -24
  131. package/src/modular/buildClientContext.ts +93 -63
  132. package/src/modular/buildCodeModel.ts +93 -128
  133. package/src/modular/buildHelperSerializers.ts +1 -0
  134. package/src/modular/buildOperations.ts +9 -110
  135. package/src/modular/buildRestorePoller.ts +239 -0
  136. package/src/modular/buildRootIndex.ts +68 -0
  137. package/src/modular/emitLoggerFile.ts +28 -0
  138. package/src/modular/emitModels.ts +0 -8
  139. package/src/modular/external-dependencies.ts +140 -0
  140. package/src/modular/helpers/clientHelpers.ts +148 -14
  141. package/src/modular/helpers/operationHelpers.ts +72 -109
  142. package/src/modular/helpers/typeHelpers.ts +8 -0
  143. package/src/modular/interfaces.ts +1 -0
  144. package/src/modular/serialization/buildSerializerFunction.ts +3 -33
  145. package/src/modular/static-helpers-metadata.ts +73 -0
  146. package/src/transform/transfromRLCOptions.ts +61 -53
  147. package/src/utils/credentialUtils.ts +41 -0
  148. package/src/utils/dirname.ts +12 -0
  149. package/src/utils/emitUtil.ts +3 -2
  150. package/src/utils/modelUtils.ts +4 -4
  151. package/src/utils/operationUtil.ts +25 -2
  152. package/src/utils/resolve-project-root.ts +28 -0
  153. package/static/static-helpers/pagingHelpers.ts +274 -0
  154. package/static/static-helpers/pollingHelpers.ts +137 -0
  155. package/static/static-helpers/serialization/build-csv-collection.ts +6 -0
  156. package/static/static-helpers/serialization/build-multi-collection.ts +13 -0
  157. package/static/static-helpers/serialization/build-pipe-collection.ts +3 -0
  158. package/static/static-helpers/serialization/build-ssv-collection.ts +3 -0
  159. package/static/static-helpers/serialization/build-tsv-collection.ts +3 -0
  160. package/dist/src/modular/buildLroFiles.d.ts +0 -24
  161. package/dist/src/modular/buildLroFiles.d.ts.map +0 -1
  162. package/dist/src/modular/buildLroFiles.js +0 -393
  163. package/dist/src/modular/buildLroFiles.js.map +0 -1
  164. package/dist/src/modular/buildPagingFiles.d.ts +0 -4
  165. package/dist/src/modular/buildPagingFiles.d.ts.map +0 -1
  166. package/dist/src/modular/buildPagingFiles.js +0 -333
  167. package/dist/src/modular/buildPagingFiles.js.map +0 -1
  168. package/src/modular/buildLroFiles.ts +0 -429
  169. package/src/modular/buildPagingFiles.ts +0 -356
@@ -8,11 +8,11 @@ import {
8
8
  import { Project, SourceFile } from "ts-morph";
9
9
  import { isRLCMultiEndpoint } from "../utils/clientUtils.js";
10
10
  import { SdkContext } from "../utils/interfaces.js";
11
- import { importLroCoreDependencies } from "./buildLroFiles.js";
12
11
  import { getDocsFromDescription } from "./helpers/docsHelpers.js";
13
12
  import { getOperationName } from "./helpers/namingHelpers.js";
14
13
  import {
15
14
  getDeserializePrivateFunction,
15
+ getExpectedStatuses,
16
16
  getOperationFunction,
17
17
  getOperationOptionsName,
18
18
  getSendPrivateFunction,
@@ -30,8 +30,7 @@ import { addImportBySymbol } from "../utils/importHelper.js";
30
30
  export function buildOperationFiles(
31
31
  client: Client,
32
32
  dpgContext: SdkContext,
33
- codeModel: ModularCodeModel,
34
- needUnexpectedHelper: boolean = true
33
+ codeModel: ModularCodeModel
35
34
  ) {
36
35
  const operationFiles = [];
37
36
  const isMultiEndpoint = isRLCMultiEndpoint(dpgContext);
@@ -58,11 +57,6 @@ export function buildOperationFiles(
58
57
  subfolder && subfolder !== "" ? subfolder + "/" : ""
59
58
  }api/${operationFileName}.ts`
60
59
  );
61
- // We need to import the lro helpers and types explicitly because ts-morph may not be able to find correct ones.
62
- importLroDependencies(
63
- operationGroupFile,
64
- operationGroup.namespaceHierarchies.length
65
- );
66
60
 
67
61
  // Import models used from ./models.ts
68
62
  // We SHOULD keep this because otherwise ts-morph will "helpfully" try to import models from the rest layer when we call fixMissingImports().
@@ -94,46 +88,13 @@ export function buildOperationFiles(
94
88
  operationGroup.namespaceHierarchies.length
95
89
  );
96
90
 
97
- // We need to import the paging helpers and types explicitly because ts-morph may not be able to find them.
98
- importPagingDependencies(
99
- srcPath,
100
- operationGroupFile,
101
- codeModel.project,
102
- subfolder,
103
- operationGroup.namespaceHierarchies.length
104
- );
91
+ const indexPathPrefix =
92
+ "../".repeat(operationGroup.namespaceHierarchies.length) || "./";
93
+ operationGroupFile.addImportDeclaration({
94
+ namedImports: [`${client.rlcClientName} as Client`],
95
+ moduleSpecifier: `${indexPathPrefix}index.js`
96
+ });
105
97
 
106
- const namedImports: string[] = [];
107
- if (isMultiEndpoint) {
108
- namedImports.push(`Client`);
109
- if (needUnexpectedHelper) {
110
- namedImports.push("UnexpectedHelper");
111
- }
112
- operationGroupFile.addImportDeclarations([
113
- {
114
- moduleSpecifier: `../${"../".repeat(
115
- operationGroup.namespaceHierarchies.length
116
- )}rest/${subfolder}/index.js`,
117
- namedImports
118
- }
119
- ]);
120
- } else {
121
- if (needUnexpectedHelper) {
122
- namedImports.push("isUnexpected");
123
- }
124
- const rlcClientName = client.rlcClientName;
125
- namedImports.push(`${rlcClientName} as Client`);
126
- operationGroupFile.addImportDeclarations([
127
- {
128
- moduleSpecifier: `${
129
- subfolder && subfolder !== "" ? "../" : ""
130
- }${"../".repeat(
131
- operationGroup.namespaceHierarchies.length + 1
132
- )}rest/index.js`,
133
- namedImports
134
- }
135
- ]);
136
- }
137
98
  operationGroup.operations.forEach((o) => {
138
99
  const operationDeclaration = getOperationFunction(o, clientType);
139
100
  const sendOperationDeclaration = getSendPrivateFunction(
@@ -144,8 +105,6 @@ export function buildOperationFiles(
144
105
  );
145
106
  const deserializeOperationDeclaration = getDeserializePrivateFunction(
146
107
  o,
147
- isMultiEndpoint,
148
- needUnexpectedHelper,
149
108
  codeModel.runtimeImports
150
109
  );
151
110
  operationGroupFile.addFunctions([
@@ -171,9 +130,6 @@ export function buildOperationFiles(
171
130
  addImportsToFiles(codeModel.runtimeImports, operationGroupFile);
172
131
  addImportBySymbol("serializeRecord", operationGroupFile);
173
132
 
174
- operationGroupFile.fixMissingImports();
175
- // have to fixUnusedIdentifiers after everything get generated.
176
- operationGroupFile.fixUnusedIdentifiers();
177
133
  operationFiles.push(operationGroupFile);
178
134
  }
179
135
  return operationFiles;
@@ -246,64 +202,6 @@ export function importDeserializeUtils(
246
202
  });
247
203
  }
248
204
  }
249
- // Import all deserializeUtil and then let ts-morph clean up the unused ones
250
- // we can't fixUnusedIdentifiers here because the operaiton files are still being generated.
251
- // sourceFile.fixUnusedIdentifiers();
252
- export function importPagingDependencies(
253
- srcPath: string,
254
- sourceFile: SourceFile,
255
- project: Project,
256
- subfolder: string = "",
257
- importLayer: number = 0
258
- ) {
259
- const pagingTypes = project.getSourceFile(
260
- `${srcPath}/${subfolder !== "" ? subfolder + "/" : ""}models/pagingTypes.ts`
261
- );
262
-
263
- if (!pagingTypes) {
264
- return;
265
- }
266
-
267
- const exportedPaingTypes = [...pagingTypes.getExportedDeclarations().keys()];
268
-
269
- sourceFile.addImportDeclaration({
270
- moduleSpecifier: `${"../".repeat(importLayer + 1)}models/pagingTypes.js`,
271
- namedImports: exportedPaingTypes
272
- });
273
-
274
- const pagingHelper = project.getSourceFile(
275
- `${srcPath}/${subfolder !== "" ? subfolder + "/" : ""}api/pagingHelpers.ts`
276
- );
277
-
278
- if (!pagingHelper) {
279
- return;
280
- }
281
-
282
- const exportedPaingHelpers = [
283
- ...pagingHelper.getExportedDeclarations().keys()
284
- ];
285
-
286
- sourceFile.addImportDeclaration({
287
- moduleSpecifier: `${
288
- importLayer === 0 ? "./" : "../".repeat(importLayer)
289
- }pagingHelpers.js`,
290
- namedImports: exportedPaingHelpers
291
- });
292
- }
293
-
294
- export function importLroDependencies(
295
- sourceFile: SourceFile,
296
- importLayer: number = 0
297
- ) {
298
- sourceFile.addImportDeclaration({
299
- moduleSpecifier: `${
300
- importLayer === 0 ? "./" : "../".repeat(importLayer)
301
- }pollingHelpers.js`,
302
- namedImports: ["getLongRunningPoller"]
303
- });
304
-
305
- importLroCoreDependencies(sourceFile);
306
- }
307
205
 
308
206
  /**
309
207
  * This function generates the interfaces for each operation options
@@ -383,6 +281,7 @@ export function buildLroDeserDetailMap(client: Client) {
383
281
  existingNames.add(deserName);
384
282
  return {
385
283
  path: `${o.method.toUpperCase()} ${o.url}`,
284
+ expectedStatusesExpression: getExpectedStatuses(o),
386
285
  deserName,
387
286
  renamedDeserName
388
287
  };
@@ -0,0 +1,239 @@
1
+ import { SourceFile } from "ts-morph";
2
+ import { isLroOnlyOperation } from "./helpers/operationHelpers.js";
3
+ import { ModularCodeModel, Client } from "./modularCodeModel.js";
4
+ import path from "path";
5
+ import { buildLroDeserDetailMap } from "./buildOperations.js";
6
+ import { getClientName } from "./helpers/namingHelpers.js";
7
+ import { NameType, normalizeName } from "@azure-tools/rlc-common";
8
+ import { resolveReference } from "../framework/reference.js";
9
+ import {
10
+ AzureCoreDependencies,
11
+ AzurePollingDependencies
12
+ } from "./external-dependencies.js";
13
+ import { PollingHelpers } from "./static-helpers-metadata.js";
14
+
15
+ export function buildRestorePoller(
16
+ codeModel: ModularCodeModel,
17
+ client: Client
18
+ ) {
19
+ const lros = client.operationGroups
20
+ .flatMap((op) => op.operations)
21
+ .filter(isLroOnlyOperation);
22
+ if (lros.length === 0) {
23
+ return;
24
+ }
25
+ const srcPath = codeModel.modularOptions.sourceRoot;
26
+ const subfolder = client.subfolder ?? "";
27
+ const filePath = path.join(
28
+ `${srcPath}/${
29
+ subfolder !== "" ? subfolder + "/" : ""
30
+ }restorePollerHelpers.ts`
31
+ );
32
+ const restorePollerFile = codeModel.project.createSourceFile(
33
+ filePath,
34
+ undefined,
35
+ {
36
+ overwrite: true
37
+ }
38
+ );
39
+
40
+ const clientNames = importClassicalClient(client, restorePollerFile);
41
+ const deserializeMap = importDeserializeHelpers(client, restorePollerFile);
42
+ const pathUncheckedReference = resolveReference(
43
+ AzureCoreDependencies.PathUncheckedResponse
44
+ );
45
+ const pollerLikeReference = resolveReference(
46
+ AzurePollingDependencies.PollerLike
47
+ );
48
+ const operationStateReference = resolveReference(
49
+ AzurePollingDependencies.OperationState
50
+ );
51
+ const operationOptionsReference = resolveReference(
52
+ AzureCoreDependencies.OperationOptions
53
+ );
54
+ const deserializeStateReference = resolveReference(
55
+ AzurePollingDependencies.DeserializeState
56
+ );
57
+ const restorePollerHelperContent = `
58
+ export interface RestorePollerOptions<
59
+ TResult,
60
+ TResponse extends ${pathUncheckedReference} = ${pathUncheckedReference}
61
+ > extends ${operationOptionsReference} {
62
+ /** Delay to wait until next poll, in milliseconds. */
63
+ updateIntervalInMs?: number;
64
+ /**
65
+ * The signal which can be used to abort requests.
66
+ */
67
+ abortSignal?: ${resolveReference(AzureCoreDependencies.AbortSignalLike)};
68
+ /** Deserialization function for raw response body */
69
+ processResponseBody?: (result: TResponse) => Promise<TResult>;
70
+ }
71
+
72
+ /**
73
+ * Creates a poller from the serialized state of another poller. This can be
74
+ * useful when you want to create pollers on a different host or a poller
75
+ * needs to be constructed after the original one is not in scope.
76
+ */
77
+ export function restorePoller<TResponse extends ${pathUncheckedReference}, TResult>(
78
+ client: ${clientNames.join(" | ")},
79
+ serializedState: string,
80
+ sourceOperation: (
81
+ ...args: any[]
82
+ ) => ${pollerLikeReference}<${operationStateReference}<TResult>, TResult>,
83
+ options?: RestorePollerOptions<TResult>
84
+ ): ${pollerLikeReference}<${operationStateReference}<TResult>, TResult> {
85
+ const pollerConfig = ${deserializeStateReference}(serializedState).config;
86
+ const { initialRequestUrl, requestMethod, metadata } = pollerConfig;
87
+ if (!initialRequestUrl || !requestMethod) {
88
+ throw new Error(
89
+ \`Invalid serialized state: \${serializedState} for sourceOperation \${sourceOperation?.name}\`
90
+ );
91
+ }
92
+ const resourceLocationConfig = metadata?.["resourceLocationConfig"] as
93
+ | ${resolveReference(AzurePollingDependencies.ResourceLocationConfig)}
94
+ | undefined;
95
+ const { deserializer, expectedStatuses = [] } =
96
+ getDeserializationHelper(initialRequestUrl, requestMethod) ?? {};
97
+ const deserializeHelper = options?.processResponseBody ?? deserializer;
98
+ if (!deserializeHelper) {
99
+ throw new Error(
100
+ \`Please ensure the operation is in this client! We can't find its deserializeHelper for \${sourceOperation?.name}.\`
101
+ );
102
+ }
103
+ return ${resolveReference(PollingHelpers.GetLongRunningPoller)}(
104
+ (client as any)["_client"] ?? client,
105
+ deserializeHelper as (result: TResponse) => Promise<TResult>,
106
+ expectedStatuses,
107
+ {
108
+ updateIntervalInMs: options?.updateIntervalInMs,
109
+ abortSignal: options?.abortSignal,
110
+ resourceLocationConfig,
111
+ restoreFrom: serializedState,
112
+ initialRequestUrl
113
+ }
114
+ );
115
+ }
116
+
117
+ interface DeserializationHelper {
118
+ deserializer: Function;
119
+ expectedStatuses: string[];
120
+ }
121
+
122
+ const deserializeMap: Record<string, DeserializationHelper> = {
123
+ ${deserializeMap.join(",\n")}
124
+ };
125
+
126
+ function getDeserializationHelper(
127
+ urlStr: string,
128
+ method: string
129
+ ): DeserializationHelper | undefined {
130
+ const path = new URL(urlStr).pathname;
131
+ const pathParts = path.split("/");
132
+
133
+ // Traverse list to match the longest candidate
134
+ // matchedLen: the length of candidate path
135
+ // matchedValue: the matched status code array
136
+ let matchedLen = -1,
137
+ matchedValue: DeserializationHelper | undefined;
138
+
139
+ // Iterate the responseMap to find a match
140
+ for (const [key, value] of Object.entries(deserializeMap)) {
141
+ // Extracting the path from the map key which is in format
142
+ // GET /path/foo
143
+ if (!key.startsWith(method)) {
144
+ continue;
145
+ }
146
+ const candidatePath = getPathFromMapKey(key);
147
+ // Get each part of the url path
148
+ const candidateParts = candidatePath.split("/");
149
+
150
+ // track if we have found a match to return the values found.
151
+ let found = true;
152
+ for (
153
+ let i = candidateParts.length - 1, j = pathParts.length - 1;
154
+ i >= 1 && j >= 1;
155
+ i--, j--
156
+ ) {
157
+ if (
158
+ candidateParts[i]?.startsWith("{") &&
159
+ candidateParts[i]?.indexOf("}") !== -1
160
+ ) {
161
+ const start = candidateParts[i]!.indexOf("}") + 1,
162
+ end = candidateParts[i]?.length;
163
+ // If the current part of the candidate is a "template" part
164
+ // Try to use the suffix of pattern to match the path
165
+ // {guid} ==> $
166
+ // {guid}:export ==> :export$
167
+ const isMatched = new RegExp(
168
+ \`\${candidateParts[i]?.slice(start, end)}\`
169
+ ).test(pathParts[j] || "");
170
+
171
+ if (!isMatched) {
172
+ found = false;
173
+ break;
174
+ }
175
+ continue;
176
+ }
177
+
178
+ // If the candidate part is not a template and
179
+ // the parts don't match mark the candidate as not found
180
+ // to move on with the next candidate path.
181
+ if (candidateParts[i] !== pathParts[j]) {
182
+ found = false;
183
+ break;
184
+ }
185
+ }
186
+
187
+ // We finished evaluating the current candidate parts
188
+ // Update the matched value if and only if we found the longer pattern
189
+ if (found && candidatePath.length > matchedLen) {
190
+ matchedLen = candidatePath.length;
191
+ matchedValue = value;
192
+ }
193
+ }
194
+
195
+ return matchedValue;
196
+ }
197
+
198
+ function getPathFromMapKey(mapKey: string): string {
199
+ const pathStart = mapKey.indexOf("/");
200
+ return mapKey.slice(pathStart);
201
+ }
202
+ `;
203
+ restorePollerFile.addStatements(restorePollerHelperContent);
204
+ }
205
+
206
+ function importDeserializeHelpers(client: Client, sourceFile: SourceFile) {
207
+ const deserializeDetails = buildLroDeserDetailMap(client);
208
+ const deserializeMap: string[] = [];
209
+ for (const [key, value] of deserializeDetails.entries()) {
210
+ sourceFile.addImportDeclaration({
211
+ namedImports: value.map((detail) =>
212
+ detail.renamedDeserName
213
+ ? `${detail.deserName} as ${detail.renamedDeserName}`
214
+ : detail.deserName
215
+ ),
216
+ moduleSpecifier: key
217
+ });
218
+ value.forEach((detail) => {
219
+ deserializeMap.push(
220
+ `"${detail.path}": { deserializer: ${
221
+ detail.renamedDeserName ?? detail.deserName
222
+ }, expectedStatuses: ${detail.expectedStatusesExpression} }`
223
+ );
224
+ });
225
+ }
226
+ return deserializeMap;
227
+ }
228
+
229
+ function importClassicalClient(
230
+ client: Client,
231
+ sourceFile: SourceFile
232
+ ): string[] {
233
+ const classicalClientName = `${getClientName(client)}Client`;
234
+ sourceFile.addImportDeclaration({
235
+ namedImports: [`${classicalClientName}`],
236
+ moduleSpecifier: `./${normalizeName(classicalClientName, NameType.File)}.js`
237
+ });
238
+ return [classicalClientName];
239
+ }
@@ -2,6 +2,8 @@ import { NameType, normalizeName } from "@azure-tools/rlc-common";
2
2
  import { Project, SourceFile } from "ts-morph";
3
3
  import { getClientName } from "./helpers/namingHelpers.js";
4
4
  import { Client, ModularCodeModel } from "./modularCodeModel.js";
5
+ import { resolveReference } from "../framework/reference.js";
6
+ import { PagingHelpers } from "./static-helpers-metadata.js";
5
7
 
6
8
  export function buildRootIndex(
7
9
  client: Client,
@@ -55,6 +57,72 @@ export function buildRootIndex(
55
57
  subfolder,
56
58
  true
57
59
  );
60
+
61
+ exportPagingTypes(codeModel, rootIndexFile);
62
+ }
63
+
64
+ /**
65
+ * This is a temporary solution for adding paging exports. Eventually we will have the binder generate the exports automatically.
66
+ */
67
+ function exportPagingTypes(
68
+ codeModel: ModularCodeModel,
69
+ rootIndexFile: SourceFile
70
+ ) {
71
+ if (!hasPaging(codeModel)) {
72
+ return;
73
+ }
74
+
75
+ const existingExports = getExistingExports(rootIndexFile);
76
+ const namedExports = [
77
+ resolveReference(PagingHelpers.PageSettings),
78
+ resolveReference(PagingHelpers.ContinuablePage),
79
+ resolveReference(PagingHelpers.PagedAsyncIterableIterator)
80
+ ];
81
+
82
+ const newNamedExports = getNewNamedExports(namedExports, existingExports);
83
+
84
+ if (newNamedExports.length > 0) {
85
+ addExportsToRootIndexFile(rootIndexFile, newNamedExports);
86
+ }
87
+ }
88
+
89
+ function hasPaging(codeModel: ModularCodeModel): boolean {
90
+ return codeModel.clients.some((c) =>
91
+ c.operationGroups.some((og) =>
92
+ og.operations.some(
93
+ (op) =>
94
+ op.discriminator === "paging" || op.discriminator === "lropaging"
95
+ )
96
+ )
97
+ );
98
+ }
99
+
100
+ function getExistingExports(rootIndexFile: SourceFile): Set<string> {
101
+ return new Set(
102
+ rootIndexFile
103
+ .getExportDeclarations()
104
+ .flatMap((exportDecl) =>
105
+ exportDecl.getNamedExports().map((namedExport) => namedExport.getName())
106
+ )
107
+ );
108
+ }
109
+
110
+ function getNewNamedExports(
111
+ namedExports: string[],
112
+ existingExports: Set<string>
113
+ ): string[] {
114
+ return namedExports.filter(
115
+ (namedExport) => !existingExports.has(namedExport)
116
+ );
117
+ }
118
+
119
+ function addExportsToRootIndexFile(
120
+ rootIndexFile: SourceFile,
121
+ newNamedExports: string[]
122
+ ) {
123
+ rootIndexFile.addExportDeclaration({
124
+ namedExports: newNamedExports
125
+ });
58
126
  }
59
127
 
60
128
  function exportRestoreHelpers(
@@ -0,0 +1,28 @@
1
+ import { Project } from "ts-morph";
2
+ import { ModularCodeModel } from "./modularCodeModel.js";
3
+
4
+ export function emitLoggerFile(
5
+ codeModel: ModularCodeModel,
6
+ project: Project,
7
+ srcPath: string = "src"
8
+ ) {
9
+ if (codeModel.options.flavor !== "azure") {
10
+ return;
11
+ }
12
+
13
+ const sourceFile = project.createSourceFile(`${srcPath}/logger.ts`, "", {
14
+ overwrite: true
15
+ });
16
+
17
+ sourceFile.addImportDeclaration({
18
+ namedImports: ["createClientLogger"],
19
+ moduleSpecifier: "@azure/logger"
20
+ });
21
+
22
+ const name =
23
+ codeModel.options.packageDetails?.nameWithoutScope ??
24
+ codeModel.options.packageDetails?.name;
25
+ sourceFile.addStatements(
26
+ `export const logger = createClientLogger("${name}");`
27
+ );
28
+ }
@@ -253,7 +253,6 @@ export function buildModels(
253
253
 
254
254
  const projectRootFromModels = codeModel.clients.length > 1 ? "../.." : "../";
255
255
  addImportsToFiles(codeModel.runtimeImports, modelsFile, {
256
- rlcIndex: path.posix.join(projectRootFromModels, "rest", "index.js"),
257
256
  serializerHelpers: path.posix.join(
258
257
  projectRootFromModels,
259
258
  "helpers",
@@ -394,13 +393,6 @@ export function buildModelsOptions(
394
393
  }
395
394
  ]);
396
395
 
397
- modelOptionsFile.fixMissingImports(
398
- {},
399
- {
400
- importModuleSpecifierPreference: "shortest",
401
- importModuleSpecifierEnding: "js"
402
- }
403
- );
404
396
  modelOptionsFile
405
397
  .getImportDeclarations()
406
398
  .filter((id) => {
@@ -0,0 +1,140 @@
1
+ import { CoreDependencies } from "../framework/dependency.js";
2
+
3
+ export const DefaultCoreDependencies: CoreDependencies = {
4
+ Client: {
5
+ kind: "externalDependency",
6
+ name: "Client",
7
+ module: "@typespec/ts-http-runtime"
8
+ },
9
+ ClientOptions: {
10
+ kind: "externalDependency",
11
+ name: "ClientOptions",
12
+ module: "@typespec/ts-http-runtime"
13
+ },
14
+ Pipeline: {
15
+ kind: "externalDependency",
16
+ name: "Pipeline",
17
+ module: "@typespec/ts-http-runtime"
18
+ },
19
+ getClient: {
20
+ kind: "externalDependency",
21
+ name: "getClient",
22
+ module: "@typespec/ts-http-runtime"
23
+ },
24
+ RestError: {
25
+ kind: "externalDependency",
26
+ name: "RestError",
27
+ module: "@typespec/ts-http-runtime"
28
+ },
29
+ OperationOptions: {
30
+ kind: "externalDependency",
31
+ name: "OperationOptions",
32
+ module: "@typespec/ts-http-runtime"
33
+ },
34
+ PathUncheckedResponse: {
35
+ kind: "externalDependency",
36
+ name: "PathUncheckedResponse",
37
+ module: "@typespec/ts-http-runtime"
38
+ },
39
+ AbortSignalLike: {
40
+ kind: "externalDependency",
41
+ name: "AbortSignalLike",
42
+ module: "@typespec/ts-http-runtime"
43
+ },
44
+ createRestError: {
45
+ kind: "externalDependency",
46
+ name: "createRestError",
47
+ module: "@typespec/ts-http-runtime"
48
+ },
49
+ operationOptionsToRequestParameters: {
50
+ kind: "externalDependency",
51
+ name: "operationOptionsToRequestParameters",
52
+ module: "@typespec/ts-http-runtime"
53
+ },
54
+ uint8ArrayToString: {
55
+ kind: "externalDependency",
56
+ name: "uint8ArrayToString",
57
+ module: "@typespec/ts-http-runtime"
58
+ }
59
+ } as const;
60
+
61
+ export const AzurePollingDependencies = {
62
+ PollerLike: {
63
+ kind: "externalDependency",
64
+ module: "@azure/core-lro",
65
+ name: "PollerLike"
66
+ },
67
+ OperationState: {
68
+ kind: "externalDependency",
69
+ module: "@azure/core-lro",
70
+ name: "OperationState"
71
+ },
72
+ DeserializeState: {
73
+ kind: "externalDependency",
74
+ module: "@azure/core-lro",
75
+ name: "deserializeState"
76
+ },
77
+ ResourceLocationConfig: {
78
+ kind: "externalDependency",
79
+ module: "@azure/core-lro",
80
+ name: "ResourceLocationConfig"
81
+ }
82
+ };
83
+
84
+ export const AzureCoreDependencies: CoreDependencies = {
85
+ Client: {
86
+ kind: "externalDependency",
87
+ module: "@azure-rest/core-client",
88
+ name: "Client"
89
+ },
90
+ ClientOptions: {
91
+ kind: "externalDependency",
92
+ module: "@azure-rest/core-client",
93
+ name: "ClientOptions"
94
+ },
95
+ Pipeline: {
96
+ kind: "externalDependency",
97
+ module: "@azure-rest/core-client",
98
+ name: "Pipeline"
99
+ },
100
+ getClient: {
101
+ kind: "externalDependency",
102
+ module: "@azure-rest/core-client",
103
+ name: "getClient"
104
+ },
105
+ RestError: {
106
+ kind: "externalDependency",
107
+ module: "@azure-rest/core-client",
108
+ name: "RestError"
109
+ },
110
+ OperationOptions: {
111
+ kind: "externalDependency",
112
+ module: "@azure-rest/core-client",
113
+ name: "OperationOptions"
114
+ },
115
+ PathUncheckedResponse: {
116
+ kind: "externalDependency",
117
+ module: "@azure-rest/core-client",
118
+ name: "PathUncheckedResponse"
119
+ },
120
+ AbortSignalLike: {
121
+ kind: "externalDependency",
122
+ module: "@azure/abort-controller",
123
+ name: "AbortSignalLike"
124
+ },
125
+ createRestError: {
126
+ kind: "externalDependency",
127
+ module: "@azure-rest/core-client",
128
+ name: "createRestError"
129
+ },
130
+ operationOptionsToRequestParameters: {
131
+ kind: "externalDependency",
132
+ module: "@azure-rest/core-client",
133
+ name: "operationOptionsToRequestParameters"
134
+ },
135
+ uint8ArrayToString: {
136
+ kind: "externalDependency",
137
+ module: "@azure/core-util",
138
+ name: "uint8ArrayToString"
139
+ }
140
+ };