@azure-tools/typespec-ts 0.14.0 → 0.15.0-alpha.20230822.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.
Files changed (141) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/src/index.d.ts +1 -5
  3. package/dist/src/index.d.ts.map +1 -1
  4. package/dist/src/index.js +148 -78
  5. package/dist/src/index.js.map +1 -1
  6. package/dist/src/lib.d.ts.map +1 -1
  7. package/dist/src/lib.js +4 -2
  8. package/dist/src/lib.js.map +1 -1
  9. package/dist/src/modular/buildClassicalClient.d.ts +1 -1
  10. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  11. package/dist/src/modular/buildClassicalClient.js +27 -15
  12. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  13. package/dist/src/modular/buildClientContext.d.ts +1 -1
  14. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  15. package/dist/src/modular/buildClientContext.js +16 -7
  16. package/dist/src/modular/buildClientContext.js.map +1 -1
  17. package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
  18. package/dist/src/modular/buildCodeModel.js +59 -12
  19. package/dist/src/modular/buildCodeModel.js.map +1 -1
  20. package/dist/src/modular/buildOperations.d.ts +2 -1
  21. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  22. package/dist/src/modular/buildOperations.js +25 -29
  23. package/dist/src/modular/buildOperations.js.map +1 -1
  24. package/dist/src/modular/buildProjectFiles.d.ts +2 -2
  25. package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
  26. package/dist/src/modular/buildProjectFiles.js +284 -145
  27. package/dist/src/modular/buildProjectFiles.js.map +1 -1
  28. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  29. package/dist/src/modular/buildRootIndex.js +5 -5
  30. package/dist/src/modular/buildRootIndex.js.map +1 -1
  31. package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
  32. package/dist/src/modular/buildSubpathIndex.js +9 -2
  33. package/dist/src/modular/buildSubpathIndex.js.map +1 -1
  34. package/dist/src/modular/emitModels.d.ts +3 -2
  35. package/dist/src/modular/emitModels.d.ts.map +1 -1
  36. package/dist/src/modular/emitModels.js +40 -7
  37. package/dist/src/modular/emitModels.js.map +1 -1
  38. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  39. package/dist/src/modular/helpers/clientHelpers.js +5 -3
  40. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  41. package/dist/src/modular/helpers/docsHelpers.d.ts +3 -0
  42. package/dist/src/modular/helpers/docsHelpers.d.ts.map +1 -0
  43. package/dist/src/modular/helpers/docsHelpers.js +10 -0
  44. package/dist/src/modular/helpers/docsHelpers.js.map +1 -0
  45. package/dist/src/modular/helpers/operationHelpers.d.ts +11 -4
  46. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  47. package/dist/src/modular/helpers/operationHelpers.js +197 -56
  48. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  49. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  50. package/dist/src/modular/helpers/typeHelpers.js +6 -0
  51. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  52. package/dist/src/modular/modularCodeModel.d.ts +2 -0
  53. package/dist/src/modular/modularCodeModel.d.ts.map +1 -1
  54. package/dist/src/transform/transform.d.ts +5 -8
  55. package/dist/src/transform/transform.d.ts.map +1 -1
  56. package/dist/src/transform/transform.js +23 -13
  57. package/dist/src/transform/transform.js.map +1 -1
  58. package/dist/src/transform/transformApiVersionInfo.d.ts +2 -1
  59. package/dist/src/transform/transformApiVersionInfo.d.ts.map +1 -1
  60. package/dist/src/transform/transformApiVersionInfo.js.map +1 -1
  61. package/dist/src/transform/transformHelperFunctionDetails.d.ts +2 -1
  62. package/dist/src/transform/transformHelperFunctionDetails.d.ts.map +1 -1
  63. package/dist/src/transform/transformHelperFunctionDetails.js +4 -10
  64. package/dist/src/transform/transformHelperFunctionDetails.js.map +1 -1
  65. package/dist/src/transform/transformParameters.d.ts +2 -12
  66. package/dist/src/transform/transformParameters.d.ts.map +1 -1
  67. package/dist/src/transform/transformParameters.js +6 -47
  68. package/dist/src/transform/transformParameters.js.map +1 -1
  69. package/dist/src/transform/transformPaths.d.ts +2 -2
  70. package/dist/src/transform/transformPaths.d.ts.map +1 -1
  71. package/dist/src/transform/transformPaths.js.map +1 -1
  72. package/dist/src/transform/transformResponses.d.ts +2 -2
  73. package/dist/src/transform/transformResponses.d.ts.map +1 -1
  74. package/dist/src/transform/transformResponses.js +5 -1
  75. package/dist/src/transform/transformResponses.js.map +1 -1
  76. package/dist/src/transform/transformSchemas.d.ts +2 -2
  77. package/dist/src/transform/transformSchemas.d.ts.map +1 -1
  78. package/dist/src/transform/transformSchemas.js.map +1 -1
  79. package/dist/src/transform/transformTelemetryInfo.d.ts +4 -0
  80. package/dist/src/transform/transformTelemetryInfo.d.ts.map +1 -0
  81. package/dist/src/transform/transformTelemetryInfo.js +42 -0
  82. package/dist/src/transform/transformTelemetryInfo.js.map +1 -0
  83. package/dist/src/transform/transfromRLCOptions.d.ts +4 -2
  84. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  85. package/dist/src/transform/transfromRLCOptions.js +72 -19
  86. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  87. package/dist/src/utils/clientUtils.d.ts +2 -1
  88. package/dist/src/utils/clientUtils.d.ts.map +1 -1
  89. package/dist/src/utils/clientUtils.js.map +1 -1
  90. package/dist/src/utils/interfaces.d.ts +13 -0
  91. package/dist/src/utils/interfaces.d.ts.map +1 -0
  92. package/dist/src/utils/interfaces.js +2 -0
  93. package/dist/src/utils/interfaces.js.map +1 -0
  94. package/dist/src/utils/modelUtils.d.ts +1 -1
  95. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  96. package/dist/src/utils/modelUtils.js +25 -20
  97. package/dist/src/utils/modelUtils.js.map +1 -1
  98. package/dist/src/utils/operationUtil.d.ts +15 -4
  99. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  100. package/dist/src/utils/operationUtil.js +65 -1
  101. package/dist/src/utils/operationUtil.js.map +1 -1
  102. package/dist/tsconfig.tsbuildinfo +1 -1
  103. package/package.json +28 -18
  104. package/src/index.ts +231 -129
  105. package/src/lib.ts +4 -2
  106. package/src/modular/buildClassicalClient.ts +33 -16
  107. package/src/modular/buildClientContext.ts +18 -8
  108. package/src/modular/buildCodeModel.ts +71 -13
  109. package/src/modular/buildOperations.ts +31 -36
  110. package/src/modular/buildProjectFiles.ts +329 -162
  111. package/src/modular/buildRootIndex.ts +5 -7
  112. package/src/modular/buildSubpathIndex.ts +9 -2
  113. package/src/modular/emitModels.ts +55 -9
  114. package/src/modular/helpers/clientHelpers.ts +5 -3
  115. package/src/modular/helpers/docsHelpers.ts +10 -0
  116. package/src/modular/helpers/operationHelpers.ts +328 -75
  117. package/src/modular/helpers/typeHelpers.ts +6 -0
  118. package/src/modular/modularCodeModel.ts +2 -0
  119. package/src/transform/transform.ts +24 -31
  120. package/src/transform/transformApiVersionInfo.ts +1 -1
  121. package/src/transform/transformHelperFunctionDetails.ts +12 -11
  122. package/src/transform/transformParameters.ts +20 -63
  123. package/src/transform/transformPaths.ts +5 -5
  124. package/src/transform/transformResponses.ts +10 -6
  125. package/src/transform/transformSchemas.ts +2 -2
  126. package/src/transform/transformTelemetryInfo.ts +72 -0
  127. package/src/transform/transfromRLCOptions.ts +100 -23
  128. package/src/utils/clientUtils.ts +2 -4
  129. package/src/utils/interfaces.ts +14 -0
  130. package/src/utils/modelUtils.ts +18 -11
  131. package/src/utils/operationUtil.ts +92 -6
  132. package/dist/src/modular/helpers/fixmeHelpers.d.ts +0 -2
  133. package/dist/src/modular/helpers/fixmeHelpers.d.ts.map +0 -1
  134. package/dist/src/modular/helpers/fixmeHelpers.js +0 -4
  135. package/dist/src/modular/helpers/fixmeHelpers.js.map +0 -1
  136. package/dist/src/modular/helpers/parameterHelpers.d.ts +0 -3
  137. package/dist/src/modular/helpers/parameterHelpers.d.ts.map +0 -1
  138. package/dist/src/modular/helpers/parameterHelpers.js +0 -16
  139. package/dist/src/modular/helpers/parameterHelpers.js.map +0 -1
  140. package/src/modular/helpers/fixmeHelpers.ts +0 -3
  141. package/src/modular/helpers/parameterHelpers.ts +0 -17
@@ -6,6 +6,7 @@ import {
6
6
  import { toPascalCase } from "../../utils/casingUtils.js";
7
7
  import {
8
8
  BodyParameter,
9
+ ModularCodeModel,
9
10
  Operation,
10
11
  Parameter,
11
12
  Property,
@@ -20,7 +21,14 @@ import {
20
21
  normalizeName
21
22
  } from "@azure-tools/rlc-common";
22
23
  import { getOperationName } from "./namingHelpers.js";
23
- import { getFixmeForMultilineDocs } from "./fixmeHelpers.js";
24
+ import {
25
+ getFixmeForMultilineDocs,
26
+ getDocsFromDescription
27
+ } from "./docsHelpers.js";
28
+ import {
29
+ getCollectionFormatHelper,
30
+ hasCollectionFormatInfo
31
+ } from "../../utils/operationUtil.js";
24
32
 
25
33
  function getRLCResponseType(rlcResponse?: OperationResponse) {
26
34
  if (!rlcResponse?.responses) {
@@ -41,11 +49,9 @@ function getRLCResponseType(rlcResponse?: OperationResponse) {
41
49
 
42
50
  export function getSendPrivateFunction(
43
51
  operation: Operation,
44
- clientType: string
52
+ clientType: string,
53
+ importSet: Map<string, Set<string>>
45
54
  ): OptionalKind<FunctionDeclarationStructure> {
46
- if (operation.name === "uploadTestFile") {
47
- operation;
48
- }
49
55
  const parameters = getOperationSignatureParameters(operation, clientType);
50
56
  const { name } = getOperationName(operation);
51
57
 
@@ -65,7 +71,8 @@ export function getSendPrivateFunction(
65
71
  `return context.path("${operationPath}", ${getPathParameters(
66
72
  operation
67
73
  )}).${operationMethod}({...operationOptionsToRequestParameters(options), ${getRequestParameters(
68
- operation
74
+ operation,
75
+ importSet
69
76
  )}});`
70
77
  );
71
78
 
@@ -78,7 +85,8 @@ export function getSendPrivateFunction(
78
85
  export function getDeserializePrivateFunction(
79
86
  operation: Operation,
80
87
  needSubClient: boolean,
81
- needUnexpectedHelper: boolean
88
+ needUnexpectedHelper: boolean,
89
+ importSet: Map<string, Set<string>>
82
90
  ): OptionalKind<FunctionDeclarationStructure> {
83
91
  const { name } = getOperationName(operation);
84
92
 
@@ -126,12 +134,21 @@ export function getDeserializePrivateFunction(
126
134
  statements.push(`return result.body`);
127
135
  } else if (response?.type?.elementType) {
128
136
  statements.push(
129
- `return ${deserializeResponseValue(response.type, "result.body")}`
137
+ `return ${deserializeResponseValue(
138
+ response.type,
139
+ "result.body",
140
+ importSet,
141
+ response.type.nullable !== undefined ? !response.type.nullable : false
142
+ )}`
130
143
  );
131
144
  } else if (response?.type?.properties) {
132
145
  statements.push(
133
146
  `return {`,
134
- getResponseMapping(response.type.properties ?? []).join(","),
147
+ getResponseMapping(
148
+ response.type.properties ?? [],
149
+ "result.body",
150
+ importSet
151
+ ).join(","),
135
152
  `}`
136
153
  );
137
154
  } else if (returnType.type === "void") {
@@ -223,7 +240,10 @@ export function getOperationFunction(
223
240
 
224
241
  const { name, fixme = [] } = getOperationName(operation);
225
242
  const functionStatement: OptionalKind<FunctionDeclarationStructure> = {
226
- docs: [operation.description, ...getFixmeForMultilineDocs(fixme)],
243
+ docs: [
244
+ ...getDocsFromDescription(operation.description),
245
+ ...getFixmeForMultilineDocs(fixme)
246
+ ],
227
247
  isAsync: true,
228
248
  isExported: true,
229
249
  name: normalizeName(operation.name, NameType.Operation, true),
@@ -244,10 +264,16 @@ export function getOperationFunction(
244
264
  };
245
265
  }
246
266
 
247
- export function getOperationOptionsName(operation: Operation) {
248
- return `${toPascalCase(operation.groupName)}${toPascalCase(
249
- operation.name
250
- )}Options`;
267
+ export function getOperationOptionsName(
268
+ operation: Operation,
269
+ includeGroupName = false
270
+ ) {
271
+ const prefix = includeGroupName ? toPascalCase(operation.groupName) : "";
272
+ const optionName = `${prefix}${toPascalCase(operation.name)}Options`;
273
+ if (operation.bodyParameter?.type.name === optionName) {
274
+ return optionName.replace(/Options$/, "RequestOptions");
275
+ }
276
+ return optionName;
251
277
  }
252
278
 
253
279
  /**
@@ -255,7 +281,10 @@ export function getOperationOptionsName(operation: Operation) {
255
281
  * RLC internally. This will translate High Level parameters into the RLC ones.
256
282
  * Figuring out what goes in headers, body, path and qsp.
257
283
  */
258
- function getRequestParameters(operation: Operation): string {
284
+ function getRequestParameters(
285
+ operation: Operation,
286
+ importSet: Map<string, Set<string>>
287
+ ): string {
259
288
  if (!operation.parameters) {
260
289
  return "";
261
290
  }
@@ -277,7 +306,9 @@ function getRequestParameters(operation: Operation): string {
277
306
 
278
307
  for (const param of operationParameters) {
279
308
  if (param.location === "header" || param.location === "query") {
280
- parametersImplementation[param.location].push(getParameterMap(param));
309
+ parametersImplementation[param.location].push(
310
+ getParameterMap(param, importSet)
311
+ );
281
312
  }
282
313
  }
283
314
 
@@ -288,9 +319,9 @@ function getRequestParameters(operation: Operation): string {
288
319
  }
289
320
 
290
321
  if (parametersImplementation.header.length) {
291
- paramStr = `${paramStr}\nheaders: {${
292
- parametersImplementation.header.join(",\n") + ","
293
- },`;
322
+ paramStr = `${paramStr}\nheaders: {${parametersImplementation.header.join(
323
+ ",\n"
324
+ )}},`;
294
325
  }
295
326
 
296
327
  if (parametersImplementation.query.length) {
@@ -299,12 +330,18 @@ function getRequestParameters(operation: Operation): string {
299
330
  )}},`;
300
331
  }
301
332
 
302
- paramStr = `${paramStr}${buildBodyParameter(operation.bodyParameter)}`;
333
+ paramStr = `${paramStr}${buildBodyParameter(
334
+ operation.bodyParameter,
335
+ importSet
336
+ )}`;
303
337
 
304
338
  return paramStr;
305
339
  }
306
340
 
307
- function buildBodyParameter(bodyParameter: BodyParameter | undefined) {
341
+ function buildBodyParameter(
342
+ bodyParameter: BodyParameter | undefined,
343
+ importSet: Map<string, Set<string>>
344
+ ) {
308
345
  if (!bodyParameter) {
309
346
  return "";
310
347
  }
@@ -314,7 +351,17 @@ function buildBodyParameter(bodyParameter: BodyParameter | undefined) {
314
351
  for (const param of bodyParameter?.type.properties?.filter(
315
352
  (p) => !p.readonly
316
353
  ) ?? []) {
317
- bodyParts.push(getParameterMap(param));
354
+ if (param.type.type === "model" && isRequired(param)) {
355
+ bodyParts.push(
356
+ `"${param.restApiName}": {${getRequestModelMapping(
357
+ param.type,
358
+ param.clientName,
359
+ importSet
360
+ ).join(",\n")}}`
361
+ );
362
+ } else {
363
+ bodyParts.push(getParameterMap(param, importSet));
364
+ }
318
365
  }
319
366
 
320
367
  if (bodyParameter && bodyParameter.type.properties) {
@@ -323,6 +370,16 @@ function buildBodyParameter(bodyParameter: BodyParameter | undefined) {
323
370
  }
324
371
 
325
372
  if (bodyParameter.type.type === "list") {
373
+ if (bodyParameter.type.elementType?.type === "model") {
374
+ const bodyParts = getRequestModelMapping(
375
+ bodyParameter.type.elementType,
376
+ "p",
377
+ importSet
378
+ );
379
+ return `\nbody: (${bodyParameter.clientName} ?? []).map((p) => { return {
380
+ ${bodyParts.join(", ")}
381
+ };}),`;
382
+ }
326
383
  return `\nbody: ${bodyParameter.clientName},`;
327
384
  }
328
385
 
@@ -336,26 +393,46 @@ function buildBodyParameter(bodyParameter: BodyParameter | undefined) {
336
393
  /**
337
394
  * This function helps with renames, translating client names to rest api names
338
395
  */
339
- function getParameterMap(param: Parameter | Property) {
396
+ function getParameterMap(
397
+ param: Parameter | Property,
398
+ importSet: Map<string, Set<string>>
399
+ ): string {
340
400
  if (isConstant(param)) {
341
401
  return getConstantValue(param);
342
402
  }
343
403
 
344
- if (isOptionalWithouDefault(param)) {
345
- return getOptionalWithoutDefault(param);
404
+ if (hasCollectionFormatInfo((param as any).location, (param as any).format)) {
405
+ return getCollectionFormat(param as Parameter);
346
406
  }
347
407
 
348
- if (isOptionalWithDefault(param)) {
349
- return getOptionalWithDefault(param);
408
+ // if the parameter or property is optional, we don't need to handle the default value
409
+ if (isOptional(param)) {
410
+ return getOptional(param, importSet);
350
411
  }
351
412
 
352
413
  if (isRequired(param)) {
353
- return getRequired(param);
414
+ return getRequired(param, importSet);
354
415
  }
355
416
 
356
417
  throw new Error(`Parameter ${param.clientName} is not supported`);
357
418
  }
358
419
 
420
+ function getCollectionFormat(param: Parameter) {
421
+ const collectionInfo = getCollectionFormatHelper(
422
+ param.location,
423
+ param.format ?? ""
424
+ );
425
+ if (!collectionInfo) {
426
+ throw "Has collection format info but without helper function detected";
427
+ }
428
+ const isMulti = (param.format ?? "").toLowerCase() === "multi";
429
+ const additionalParam = isMulti ? `, "${param.restApiName}"` : "";
430
+ if (!param.optional) {
431
+ return `"${param.restApiName}": ${collectionInfo}(${param.clientName}${additionalParam})`;
432
+ }
433
+ return `"${param.restApiName}": options?.${param.clientName} !== undefined ? ${collectionInfo}(options?.${param.clientName}${additionalParam}): undefined`;
434
+ }
435
+
359
436
  function isContentType(param: Parameter): boolean {
360
437
  return (
361
438
  param.location === "header" &&
@@ -388,7 +465,14 @@ function isRequired(param: Parameter | Property): param is RequiredType {
388
465
  return !param.optional;
389
466
  }
390
467
 
391
- function getRequired(param: RequiredType) {
468
+ function getRequired(param: RequiredType, importSet: Map<string, Set<string>>) {
469
+ if (param.type.type === "model") {
470
+ return `"${param.restApiName}": ${getRequestModelMapping(
471
+ param.type,
472
+ param.clientName,
473
+ importSet
474
+ ).join(",")}`;
475
+ }
392
476
  return `"${param.restApiName}": ${param.clientName}`;
393
477
  }
394
478
 
@@ -415,39 +499,23 @@ function isConstant(param: Parameter | Property): param is ConstantType {
415
499
  );
416
500
  }
417
501
 
418
- type OptionalWithoutDefaultType = (Parameter | Property) & {
419
- type: { optional: true; clientDefaultValue: never };
420
- };
421
- function isOptionalWithouDefault(
422
- param: Parameter | Property
423
- ): param is OptionalWithoutDefaultType {
424
- return Boolean(param.optional && !param.clientDefaultValue);
425
- }
426
- function getOptionalWithoutDefault(param: OptionalWithoutDefaultType) {
427
- return `"${param.restApiName}": options?.${param.clientName}`;
428
- }
429
-
430
- type OptionalWithDefaultType = (Parameter | Property) & {
431
- type: { optional: true; clientDefaultValue: string };
502
+ type OptionalType = (Parameter | Property) & {
503
+ type: { optional: true };
432
504
  };
433
- function isOptionalWithDefault(
434
- param: Parameter | Property
435
- ): param is OptionalWithDefaultType {
436
- return Boolean(param.clientDefaultValue);
437
- }
438
505
 
439
- function getOptionalWithDefault(param: OptionalWithDefaultType) {
440
- return `"${param.restApiName}": options.${
441
- param.clientName
442
- } ?? ${getQuotedValue(param)}`;
506
+ function isOptional(param: Parameter | Property): param is OptionalType {
507
+ return Boolean(param.optional);
443
508
  }
444
509
 
445
- function getQuotedValue(param: OptionalWithDefaultType) {
446
- if (param.type.type === "string") {
447
- return `"${param.clientDefaultValue}"`;
448
- } else {
449
- return param.clientDefaultValue;
510
+ function getOptional(param: OptionalType, importSet: Map<string, Set<string>>) {
511
+ if (param.type.type === "model") {
512
+ return `"${param.restApiName}": {${getRequestModelMapping(
513
+ param.type,
514
+ "options?." + param.clientName + "?",
515
+ importSet
516
+ ).join(", ")}}`;
450
517
  }
518
+ return `"${param.restApiName}": options?.${param.clientName}`;
451
519
  }
452
520
 
453
521
  /**
@@ -500,29 +568,105 @@ function getNullableCheck(name: string, type: Type) {
500
568
 
501
569
  return `${name} === null ? null :`;
502
570
  }
571
+
572
+ /**
573
+ *
574
+ * This function helps translating an HLC request to RLC request,
575
+ * extracting properties from body and headers and building the RLC response object
576
+ */
577
+ function getRequestModelMapping(
578
+ modelPropertyType: Type,
579
+ propertyPath: string = "body",
580
+ importSet: Map<string, Set<string>>
581
+ ) {
582
+ if (!modelPropertyType.properties || !modelPropertyType.properties) {
583
+ return [];
584
+ }
585
+ const props: string[] = [];
586
+ const properties: Property[] = modelPropertyType.properties;
587
+ for (const property of properties) {
588
+ if (property.readonly) {
589
+ continue;
590
+ }
591
+ const propertyFullName = `${propertyPath}.${property.restApiName}`;
592
+ if (property.type.type === "model") {
593
+ let definition;
594
+ if (property.type.isCoreErrorType) {
595
+ definition = `"${property.restApiName}": ${getNullableCheck(
596
+ propertyFullName,
597
+ property.type
598
+ )} ${
599
+ !property.optional ? "" : `!${propertyFullName} ? undefined :`
600
+ } ${propertyFullName}`;
601
+ } else {
602
+ definition = `"${property.restApiName}": ${getNullableCheck(
603
+ propertyFullName,
604
+ property.type
605
+ )} ${
606
+ !property.optional ? "" : `!${propertyFullName} ? undefined :`
607
+ } {${getRequestModelMapping(
608
+ property.type,
609
+ `${propertyPath}.${property.restApiName}${
610
+ property.optional ? "?" : ""
611
+ }`,
612
+ importSet
613
+ )}}`;
614
+ }
615
+
616
+ props.push(definition);
617
+ } else {
618
+ const dot = propertyPath.endsWith("?") ? "." : "";
619
+ const restValue = `${
620
+ propertyPath ? `${propertyPath}${dot}` : `${dot}`
621
+ }["${property.clientName}"]`;
622
+ props.push(
623
+ `"${property.restApiName}": ${serializeRequestValue(
624
+ property.type,
625
+ restValue,
626
+ importSet
627
+ )}`
628
+ );
629
+ }
630
+ }
631
+
632
+ return props;
633
+ }
634
+
503
635
  /**
504
636
  * This function helps translating an RLC response to an HLC response,
505
637
  * extracting properties from body and headers and building the HLC response object
506
638
  */
507
- function getResponseMapping(
639
+ export function getResponseMapping(
508
640
  properties: Property[],
509
- propertyPath: string = "result.body"
641
+ propertyPath: string = "result.body",
642
+ importSet: Map<string, Set<string>>
510
643
  ) {
511
644
  const props: string[] = [];
512
645
  for (const property of properties) {
513
646
  // TODO: Do we need to also add headers in the result type?
514
- const propertyFullName = `${propertyPath}.${property.clientName}`;
647
+ const propertyFullName = `${propertyPath}.${property.restApiName}`;
515
648
  if (property.type.type === "model") {
516
649
  let definition;
517
650
  if (property.type.isCoreErrorType) {
518
- definition = `"${property.restApiName}": ${getNullableCheck(
651
+ definition = `"${property.clientName}": ${getNullableCheck(
519
652
  propertyFullName,
520
653
  property.type
521
654
  )} ${
522
655
  !property.optional ? "" : `!${propertyFullName} ? undefined :`
523
656
  } ${propertyFullName}`;
657
+ } else if (
658
+ (property.restApiName === "message" ||
659
+ property.restApiName === "messages") &&
660
+ (property.type.name === "ChatMessage" ||
661
+ property.type.elementType?.name === "ChatMessage")
662
+ ) {
663
+ definition = `"${property.clientName}": ${
664
+ !property.optional
665
+ ? `${propertyFullName} as any`
666
+ : `!${propertyFullName} ? undefined : ${propertyFullName} as any`
667
+ }`;
524
668
  } else {
525
- definition = `"${property.restApiName}": ${getNullableCheck(
669
+ definition = `"${property.clientName}": ${getNullableCheck(
526
670
  propertyFullName,
527
671
  property.type
528
672
  )} ${
@@ -531,7 +675,8 @@ function getResponseMapping(
531
675
  property.type.properties ?? [],
532
676
  `${propertyPath}.${property.restApiName}${
533
677
  property.optional ? "?" : ""
534
- }`
678
+ }`,
679
+ importSet
535
680
  )}}`;
536
681
  }
537
682
 
@@ -541,12 +686,28 @@ function getResponseMapping(
541
686
  const restValue = `${
542
687
  propertyPath ? `${propertyPath}${dot}` : `${dot}`
543
688
  }["${property.restApiName}"]`;
544
- props.push(
545
- `"${property.clientName}": ${deserializeResponseValue(
546
- property.type,
547
- restValue
548
- )}`
549
- );
689
+ if (
690
+ property.restApiName === "messages" &&
691
+ (property.type.name === "ChatMessage" ||
692
+ property.type.elementType?.name === "ChatMessage")
693
+ ) {
694
+ props.push(
695
+ `"${property.clientName}": ${
696
+ !property.optional
697
+ ? `${propertyFullName} as any`
698
+ : `!${propertyFullName} ? undefined : ${propertyFullName} as any`
699
+ }`
700
+ );
701
+ } else {
702
+ props.push(
703
+ `"${property.clientName}": ${deserializeResponseValue(
704
+ property.type,
705
+ restValue,
706
+ importSet,
707
+ property.optional !== undefined ? !property.optional : false
708
+ )}`
709
+ );
710
+ }
550
711
  }
551
712
  }
552
713
 
@@ -558,29 +719,100 @@ function getResponseMapping(
558
719
  * We need to drill down into Array elements to make sure that the element type is
559
720
  * deserialized correctly
560
721
  */
561
- function deserializeResponseValue(type: Type, restValue: string): string {
722
+ function deserializeResponseValue(
723
+ type: Type,
724
+ restValue: string,
725
+ importSet: Map<string, Set<string>>,
726
+ required: boolean
727
+ ): string {
728
+ const coreUtilSet = importSet.get("@azure/core-util");
562
729
  switch (type.type) {
563
730
  case "datetime":
564
- return `new Date(${restValue} ?? "")`;
565
- case "byte-array":
566
- return `Buffer.from(${restValue} ?? "")`;
731
+ return required
732
+ ? `new Date(${restValue})`
733
+ : `${restValue} !== undefined? new Date(${restValue}): undefined`;
734
+ case "combined":
735
+ return `${restValue} as any`;
567
736
  case "list":
568
737
  if (type.elementType?.type === "model") {
569
738
  return `(${restValue} ?? []).map(p => ({${getResponseMapping(
570
739
  type.elementType?.properties ?? [],
571
- "p"
740
+ "p",
741
+ importSet
572
742
  )}}))`;
573
743
  } else if (
574
744
  type.elementType?.properties?.some((p) => needsDeserialize(p.type))
575
745
  ) {
576
746
  return `(${restValue} ?? []).map(p => ${deserializeResponseValue(
577
747
  type.elementType!,
578
- "p"
748
+ "p",
749
+ importSet,
750
+ required
579
751
  )})`;
580
752
  } else {
581
753
  return restValue;
582
754
  }
755
+ case "byte-array":
756
+ if (!coreUtilSet) {
757
+ importSet.set(
758
+ "@azure/core-util",
759
+ new Set<string>().add("stringToUint8Array")
760
+ );
761
+ } else {
762
+ coreUtilSet.add("stringToUint8Array");
763
+ }
764
+ return `typeof ${restValue} === 'string'
765
+ ? stringToUint8Array(${restValue}, "${type.format ?? "base64"}")
766
+ : ${restValue}`;
767
+ default:
768
+ return restValue;
769
+ }
770
+ }
583
771
 
772
+ /**
773
+ * This function helps converting strings into JS complex types recursively.
774
+ * We need to drill down into Array elements to make sure that the element type is
775
+ * deserialized correctly
776
+ */
777
+ function serializeRequestValue(
778
+ type: Type,
779
+ restValue: string,
780
+ importSet: Map<string, Set<string>>
781
+ ): string {
782
+ const coreUtilSet = importSet.get("@azure/core-util");
783
+ switch (type.type) {
784
+ case "datetime":
785
+ return `${restValue} !== undefined ? new Date(${restValue}): undefined`;
786
+ case "list":
787
+ if (type.elementType?.type === "model") {
788
+ return `(${restValue} ?? []).map(p => ({${getRequestModelMapping(
789
+ type.elementType,
790
+ "p",
791
+ importSet
792
+ )}}))`;
793
+ } else if (
794
+ type.elementType?.properties?.some((p) => needsDeserialize(p.type))
795
+ ) {
796
+ return `(${restValue} ?? []).map(p => ${serializeRequestValue(
797
+ type.elementType!,
798
+ "p",
799
+ importSet
800
+ )})`;
801
+ } else {
802
+ return restValue;
803
+ }
804
+ case "byte-array":
805
+ if (!coreUtilSet) {
806
+ importSet.set(
807
+ "@azure/core-util",
808
+ new Set<string>().add("uint8ArrayToString")
809
+ );
810
+ } else {
811
+ coreUtilSet.add("uint8ArrayToString");
812
+ }
813
+ return `${restValue} !== undefined ? uint8ArrayToString(${restValue}, "${
814
+ type.format ?? "base64"
815
+ }"): undefined`;
584
816
  default:
585
817
  return restValue;
586
818
  }
@@ -589,3 +821,24 @@ function deserializeResponseValue(type: Type, restValue: string): string {
589
821
  function needsDeserialize(type?: Type) {
590
822
  return type?.type === "datetime" || type?.type === "model";
591
823
  }
824
+
825
+ export function hasLROOperation(codeModel: ModularCodeModel) {
826
+ return (codeModel.clients ?? []).some((c) =>
827
+ (c.operationGroups ?? []).some((og) =>
828
+ (og.operations ?? []).some(
829
+ (op) => op.discriminator === "lro" || op.discriminator === "lropaging"
830
+ )
831
+ )
832
+ );
833
+ }
834
+
835
+ export function hasPagingOperation(codeModel: ModularCodeModel) {
836
+ return (codeModel.clients ?? []).some((c) =>
837
+ (c.operationGroups ?? []).some((og) =>
838
+ (og.operations ?? []).some(
839
+ (op) =>
840
+ op.discriminator === "paging" || op.discriminator === "lropaging"
841
+ )
842
+ )
843
+ );
844
+ }
@@ -23,6 +23,12 @@ export function getType(type: Type): TypeMetadata {
23
23
  originModule: "@azure/core-auth",
24
24
  isRelative: false
25
25
  };
26
+ case "OAuth2":
27
+ return {
28
+ name: "TokenCredential",
29
+ originModule: "@azure/core-auth",
30
+ isRelative: false
31
+ };
26
32
  case "boolean":
27
33
  return { name: getNullableType(type.type, type) };
28
34
  case "constant": {
@@ -124,6 +124,7 @@ export interface Parameter {
124
124
  inDocstring?: boolean;
125
125
  inOverriden?: boolean;
126
126
  isApiVersion?: boolean;
127
+ format?: string;
127
128
  }
128
129
 
129
130
  export interface Response {
@@ -136,6 +137,7 @@ export interface Response {
136
137
 
137
138
  export interface Operation {
138
139
  name: string;
140
+ oriName?: string;
139
141
  description: string;
140
142
  summary: string;
141
143
  url: string;