@azure-tools/typespec-ts 0.15.0 → 0.16.0-alpha.20230918.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 (98) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +14 -17
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/lib.d.ts.map +1 -1
  6. package/dist/src/lib.js +3 -3
  7. package/dist/src/lib.js.map +1 -1
  8. package/dist/src/modular/buildClassicalClient.d.ts +2 -3
  9. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  10. package/dist/src/modular/buildClassicalClient.js +26 -12
  11. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  12. package/dist/src/modular/buildClientContext.d.ts +3 -3
  13. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  14. package/dist/src/modular/buildClientContext.js +5 -4
  15. package/dist/src/modular/buildClientContext.js.map +1 -1
  16. package/dist/src/modular/buildCodeModel.d.ts +3 -2
  17. package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
  18. package/dist/src/modular/buildCodeModel.js +163 -69
  19. package/dist/src/modular/buildCodeModel.js.map +1 -1
  20. package/dist/src/modular/buildOperations.d.ts +2 -2
  21. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  22. package/dist/src/modular/buildOperations.js +15 -8
  23. package/dist/src/modular/buildOperations.js.map +1 -1
  24. package/dist/src/modular/buildProjectFiles.js +2 -2
  25. package/dist/src/modular/buildProjectFiles.js.map +1 -1
  26. package/dist/src/modular/buildRootIndex.d.ts +4 -4
  27. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  28. package/dist/src/modular/buildRootIndex.js +12 -5
  29. package/dist/src/modular/buildRootIndex.js.map +1 -1
  30. package/dist/src/modular/buildSubpathIndex.d.ts +2 -2
  31. package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
  32. package/dist/src/modular/buildSubpathIndex.js +7 -4
  33. package/dist/src/modular/buildSubpathIndex.js.map +1 -1
  34. package/dist/src/modular/emitModels.d.ts +3 -3
  35. package/dist/src/modular/emitModels.d.ts.map +1 -1
  36. package/dist/src/modular/emitModels.js +28 -18
  37. package/dist/src/modular/emitModels.js.map +1 -1
  38. package/dist/src/modular/helpers/clientHelpers.js +1 -1
  39. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  40. package/dist/src/modular/helpers/operationHelpers.d.ts +1 -1
  41. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  42. package/dist/src/modular/helpers/operationHelpers.js +167 -88
  43. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  44. package/dist/src/modular/helpers/typeHelpers.d.ts +2 -2
  45. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  46. package/dist/src/modular/helpers/typeHelpers.js +13 -7
  47. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  48. package/dist/src/modular/modularCodeModel.d.ts +11 -0
  49. package/dist/src/modular/modularCodeModel.d.ts.map +1 -1
  50. package/dist/src/transform/transformHelperFunctionDetails.js +3 -4
  51. package/dist/src/transform/transformHelperFunctionDetails.js.map +1 -1
  52. package/dist/src/transform/transformParameters.d.ts +0 -10
  53. package/dist/src/transform/transformParameters.d.ts.map +1 -1
  54. package/dist/src/transform/transformParameters.js +7 -51
  55. package/dist/src/transform/transformParameters.js.map +1 -1
  56. package/dist/src/transform/transformResponses.js +3 -4
  57. package/dist/src/transform/transformResponses.js.map +1 -1
  58. package/dist/src/transform/transformSchemas.d.ts.map +1 -1
  59. package/dist/src/transform/transformSchemas.js +4 -8
  60. package/dist/src/transform/transformSchemas.js.map +1 -1
  61. package/dist/src/transform/transformTelemetryInfo.d.ts.map +1 -1
  62. package/dist/src/transform/transformTelemetryInfo.js +3 -10
  63. package/dist/src/transform/transformTelemetryInfo.js.map +1 -1
  64. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  65. package/dist/src/transform/transfromRLCOptions.js +48 -9
  66. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  67. package/dist/src/utils/modelUtils.d.ts +2 -1
  68. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  69. package/dist/src/utils/modelUtils.js +83 -73
  70. package/dist/src/utils/modelUtils.js.map +1 -1
  71. package/dist/src/utils/operationUtil.d.ts +15 -1
  72. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  73. package/dist/src/utils/operationUtil.js +82 -3
  74. package/dist/src/utils/operationUtil.js.map +1 -1
  75. package/dist/tsconfig.tsbuildinfo +1 -1
  76. package/package.json +13 -11
  77. package/src/index.ts +24 -51
  78. package/src/lib.ts +3 -3
  79. package/src/modular/buildClassicalClient.ts +29 -16
  80. package/src/modular/buildClientContext.ts +8 -9
  81. package/src/modular/buildCodeModel.ts +212 -75
  82. package/src/modular/buildOperations.ts +16 -11
  83. package/src/modular/buildProjectFiles.ts +2 -2
  84. package/src/modular/buildRootIndex.ts +19 -12
  85. package/src/modular/buildSubpathIndex.ts +10 -8
  86. package/src/modular/emitModels.ts +35 -24
  87. package/src/modular/helpers/clientHelpers.ts +1 -1
  88. package/src/modular/helpers/operationHelpers.ts +256 -127
  89. package/src/modular/helpers/typeHelpers.ts +19 -7
  90. package/src/modular/modularCodeModel.ts +11 -0
  91. package/src/transform/transformHelperFunctionDetails.ts +10 -4
  92. package/src/transform/transformParameters.ts +15 -57
  93. package/src/transform/transformResponses.ts +2 -4
  94. package/src/transform/transformSchemas.ts +5 -9
  95. package/src/transform/transformTelemetryInfo.ts +4 -18
  96. package/src/transform/transfromRLCOptions.ts +67 -9
  97. package/src/utils/modelUtils.ts +81 -72
  98. package/src/utils/operationUtil.ts +121 -4
@@ -27,10 +27,8 @@ import {
27
27
  isStringType,
28
28
  getPropertyType,
29
29
  isNumericType,
30
- getFormat,
31
30
  getMinItems,
32
31
  getMaxItems,
33
- EmitContext,
34
32
  listServices,
35
33
  Union,
36
34
  Type,
@@ -38,12 +36,12 @@ import {
38
36
  getProjectedName,
39
37
  isNullType,
40
38
  getEncode,
41
- isTemplateDeclarationOrInstance
39
+ isTemplateDeclarationOrInstance,
40
+ getFormat
42
41
  } from "@typespec/compiler";
43
42
  import {
44
43
  getAuthentication,
45
44
  getHeaderFieldName,
46
- getHttpOperation,
47
45
  getPathParamName,
48
46
  getQueryParamName,
49
47
  getServers,
@@ -54,7 +52,8 @@ import {
54
52
  HttpServer,
55
53
  isStatusCode,
56
54
  HttpOperation,
57
- isHeader
55
+ isHeader,
56
+ getHttpOperation
58
57
  } from "@typespec/http";
59
58
  import { getAddedOnVersions } from "@typespec/versioning";
60
59
  import {
@@ -65,7 +64,6 @@ import {
65
64
  isApiVersion,
66
65
  getDefaultApiVersion,
67
66
  getClientNamespaceString,
68
- createSdkContext,
69
67
  getSdkUnion,
70
68
  getAllModels,
71
69
  SdkSimpleType,
@@ -82,15 +80,24 @@ import {
82
80
  Type as HrlcType,
83
81
  Header
84
82
  } from "./modularCodeModel.js";
85
- import { transformRLCOptions } from "../transform/transfromRLCOptions.js";
86
- import { getEnrichedDefaultApiVersion } from "../utils/modelUtils.js";
83
+ import {
84
+ getEnrichedDefaultApiVersion,
85
+ isAzureCoreErrorType
86
+ } from "../utils/modelUtils.js";
87
87
  import { camelToSnakeCase, toCamelCase } from "../utils/casingUtils.js";
88
- import { RLCModel, getClientName } from "@azure-tools/rlc-common";
88
+ import {
89
+ RLCModel,
90
+ getClientName,
91
+ NameType,
92
+ normalizeName
93
+ } from "@azure-tools/rlc-common";
89
94
  import {
90
95
  getOperationGroupName,
91
- getOperationName
96
+ getOperationName,
97
+ isIgnoredHeaderParam
92
98
  } from "../utils/operationUtil.js";
93
99
  import { SdkContext } from "../utils/interfaces.js";
100
+ import { Project } from "ts-morph";
94
101
 
95
102
  interface HttpServerParameter {
96
103
  type: "endpointPath";
@@ -148,7 +155,8 @@ function isSimpleType(
148
155
  getMaxValue,
149
156
  getMinLength,
150
157
  getMaxLength,
151
- getPattern
158
+ getPattern,
159
+ getEncode
152
160
  ];
153
161
  for (const func of funcs) {
154
162
  if (func(program, type)) {
@@ -172,34 +180,44 @@ function isLro(_program: Program, operation: Operation): boolean {
172
180
  return false;
173
181
  }
174
182
 
175
- function handleDiscriminator(context: SdkContext, type: Model, model: any) {
183
+ function isDiscriminator(
184
+ context: SdkContext,
185
+ type: Model,
186
+ propertyName: string
187
+ ): boolean {
188
+ const discriminator = getDiscriminator(context.program, type);
189
+ if (discriminator && discriminator.propertyName === propertyName) {
190
+ return true;
191
+ }
192
+ return false;
193
+ }
194
+
195
+ function handleDiscriminator(context: SdkContext, type: Model) {
176
196
  const discriminator = getDiscriminator(context.program, type);
177
197
  if (discriminator) {
178
- let discriminatorProperty;
198
+ const discriminatorValues: string[] = [];
179
199
  for (const childModel of type.derivedModels) {
180
200
  const modelType = getType(context, childModel);
181
201
  for (const property of modelType.properties) {
182
202
  if (property.restApiName === discriminator.propertyName) {
183
203
  modelType.discriminatorValue = property.type.value;
184
- property.isDiscriminator = true;
185
- model.discriminatedSubtypes[property.type.value] = modelType;
186
- discriminatorProperty = property;
204
+ discriminatorValues.push(modelType.discriminatorValue);
187
205
  }
188
206
  }
189
207
  }
190
- // it is not included in properties of cadl but needed by python codegen
191
- if (discriminatorProperty) {
192
- const discriminatorType = { ...discriminatorProperty.type };
193
- discriminatorType.value = null;
194
- const propertyCopy = {
195
- ...discriminatorProperty,
208
+ // it is not included in properties of typespec but needed by python codegen
209
+ if (discriminatorValues.length > 0) {
210
+ const discriminatorInfo = {
211
+ description: `the discriminator possible values ${discriminatorValues.join(
212
+ ", "
213
+ )}`,
196
214
  isPolymorphic: true,
197
- type: discriminatorType
215
+ isDiscriminator: true
198
216
  };
199
- propertyCopy.description = "";
200
- model.properties.push(propertyCopy);
217
+ return discriminatorInfo;
201
218
  }
202
219
  }
220
+ return undefined;
203
221
  }
204
222
 
205
223
  function getEffectiveSchemaType(program: Program, type: Model | Union): Model {
@@ -258,10 +276,14 @@ function processModelProperties(
258
276
  if (newValue.properties === undefined || newValue.properties === null) {
259
277
  newValue.properties = [];
260
278
  }
261
- newValue.properties.push(emitProperty(context, property));
279
+ let newProperty = emitProperty(context, property);
280
+ if (isDiscriminator(context, model, property.name)) {
281
+ newProperty = { ...newProperty, ...handleDiscriminator(context, model) };
282
+ }
283
+ newValue.properties.push(newProperty);
262
284
  }
263
285
  // need to do discriminator outside `emitModel` to avoid infinite recursion
264
- handleDiscriminator(context, model, newValue);
286
+ // handleDiscriminator(context, model, newValue);
265
287
  }
266
288
 
267
289
  function getType(
@@ -270,8 +292,7 @@ function getType(
270
292
  options: { disableEffectiveModel?: boolean } = {}
271
293
  ): any {
272
294
  // don't cache simple type(string, int, etc) since decorators may change the result
273
- const enableCache =
274
- !isSimpleType(context.program, type) && !isEmptyModel(type);
295
+ const enableCache = !isSimpleType(context.program, type);
275
296
  const effectiveModel =
276
297
  !options.disableEffectiveModel &&
277
298
  (type.kind === "Model" || type.kind === "Union")
@@ -291,6 +312,10 @@ function getType(
291
312
  newValue = emitType(context, type);
292
313
  }
293
314
 
315
+ if (type.kind === "ModelProperty" || type.kind === "Scalar") {
316
+ newValue = applyEncoding(context.program, type, newValue);
317
+ }
318
+
294
319
  if (enableCache) {
295
320
  typesMap.set(effectiveModel, newValue);
296
321
  if (type.kind === "Union") {
@@ -328,6 +353,7 @@ type ParamBase = {
328
353
  addedOn: string | undefined;
329
354
  clientName: string;
330
355
  inOverload: boolean;
356
+ format?: string;
331
357
  };
332
358
  function emitParamBase(
333
359
  program: Program,
@@ -337,12 +363,15 @@ function emitParamBase(
337
363
  let name: string;
338
364
  let description: string = "";
339
365
  let addedOn: string | undefined;
366
+ let format: string | undefined;
340
367
 
341
368
  if (parameter.kind === "ModelProperty") {
369
+ const newParameter = applyEncoding(program, parameter, parameter);
342
370
  optional = parameter.optional;
343
371
  name = parameter.name;
344
372
  description = getDocStr(program, parameter);
345
373
  addedOn = getAddedOnVersion(program, parameter);
374
+ format = newParameter.format;
346
375
  } else {
347
376
  optional = false;
348
377
  name = "body";
@@ -353,7 +382,8 @@ function emitParamBase(
353
382
  description,
354
383
  addedOn,
355
384
  clientName: applyCasing(name, { casing: CASING }),
356
- inOverload: false
385
+ inOverload: false,
386
+ format
357
387
  };
358
388
  }
359
389
 
@@ -421,7 +451,6 @@ function emitBodyParameter(
421
451
  const type = getType(context, getBodyType(context.program, httpOperation), {
422
452
  disableEffectiveModel: true
423
453
  });
424
-
425
454
  if (type.type === "model" && type.name === "") {
426
455
  type.name = capitalize(httpOperation.operation.name) + "Request";
427
456
  }
@@ -459,9 +488,10 @@ function emitParameter(
459
488
  const paramMap: any = {
460
489
  restApiName: parameter.name,
461
490
  location: parameter.type,
462
- type: type,
491
+ type: base.format ? { ...type, format: base.format } : type,
463
492
  implementation: implementation,
464
- skipUrlEncoding: parameter.type === "endpointPath"
493
+ skipUrlEncoding: parameter.type === "endpointPath",
494
+ format: (parameter as any).format ?? base.format
465
495
  };
466
496
 
467
497
  if (paramMap.type.type === "constant") {
@@ -550,23 +580,6 @@ function emitResponseHeaders(
550
580
  return retval;
551
581
  }
552
582
 
553
- function isAzureCoreErrorType(t?: Type): boolean {
554
- if (
555
- t?.kind !== "Model" ||
556
- !["Error", "ErrorResponse", "InnerError"].includes(t.name)
557
- )
558
- return false;
559
- const namespaces = ".Azure.Core.Foundations".split(".");
560
- while (
561
- namespaces.length > 0 &&
562
- (t?.kind === "Model" || t?.kind === "Namespace") &&
563
- t.namespace?.name === namespaces.pop()
564
- ) {
565
- t = t.namespace;
566
- }
567
- return namespaces.length == 0;
568
- }
569
-
570
583
  function emitResponse(
571
584
  context: SdkContext,
572
585
  response: HttpOperationResponse,
@@ -749,6 +762,9 @@ function emitBasicOperation(
749
762
  });
750
763
 
751
764
  for (const param of httpOperation.parameters.parameters) {
765
+ if (isIgnoredHeaderParam(param)) {
766
+ continue;
767
+ }
752
768
  const emittedParam = emitParameter(context, param, "Method");
753
769
  if (isApiVersion(context, param) && apiVersionParam === undefined) {
754
770
  apiVersionParam = emittedParam;
@@ -768,7 +784,7 @@ function emitBasicOperation(
768
784
  innerResponse
769
785
  );
770
786
  if (isErrorModel(context.program, response.type)) {
771
- // * is valid status code in cadl but invalid for autorest.python
787
+ // * is valid status code in typespec but invalid for autorest.python
772
788
  if (response.statusCode === "*") {
773
789
  exceptions.push(emittedResponse);
774
790
  }
@@ -820,7 +836,7 @@ function emitBasicOperation(
820
836
  }
821
837
 
822
838
  function isReadOnly(program: Program, type: ModelProperty): boolean {
823
- // https://microsoft.github.io/cadl/standard-library/rest/operations#automatic-visibility
839
+ // https://microsoft.github.io/typespec/standard-library/http/operations#automatic-visibility
824
840
  // Only "read" should be readOnly
825
841
  const visibility = getVisibility(program, type);
826
842
  if (visibility) {
@@ -834,6 +850,7 @@ function emitProperty(
834
850
  context: SdkContext,
835
851
  property: ModelProperty
836
852
  ): Record<string, any> {
853
+ const newProperty = applyEncoding(context.program, property, property);
837
854
  let clientDefaultValue = undefined;
838
855
  const propertyDefaultKind = property.default?.kind;
839
856
  if (
@@ -845,6 +862,10 @@ function emitProperty(
845
862
  clientDefaultValue = property.default.value;
846
863
  }
847
864
 
865
+ if (propertyDefaultKind === "EnumMember") {
866
+ clientDefaultValue = property.default.value ?? property.default.name;
867
+ }
868
+
848
869
  // const [clientName, jsonName] = getPropertyNames(context, property);
849
870
  const clientName = property.name;
850
871
  const jsonName =
@@ -853,16 +874,18 @@ function emitProperty(
853
874
  if (property.model) {
854
875
  getType(context, property.model);
855
876
  }
877
+ const type = getType(context, property.type);
856
878
  return {
857
879
  clientName: applyCasing(clientName, { casing: CASING }),
858
880
  restApiName: jsonName,
859
- type: getType(context, property.type),
881
+ type: newProperty.format ? { ...type, format: newProperty.format } : type,
860
882
  optional: property.optional,
861
883
  description: getDocStr(context.program, property),
862
884
  addedOn: getAddedOnVersion(context.program, property),
863
885
  readonly:
864
886
  isReadOnly(context.program, property) || isKey(context.program, property),
865
- clientDefaultValue: clientDefaultValue
887
+ clientDefaultValue: clientDefaultValue,
888
+ format: newProperty.format
866
889
  };
867
890
  }
868
891
 
@@ -896,9 +919,35 @@ function emitModel(context: SdkContext, type: Model): Record<string, any> {
896
919
  baseModel = getType(context, type.baseModel);
897
920
  }
898
921
  const effectiveName = getEffectiveSchemaType(context.program, type).name;
899
- const modelName = effectiveName
900
- ? effectiveName
901
- : getName(context.program, type);
922
+ const overridedModelName =
923
+ getProjectedName(context.program, type, "javascript") ??
924
+ getProjectedName(context.program, type, "client") ??
925
+ getFriendlyName(context.program, type);
926
+ let modelName =
927
+ overridedModelName ??
928
+ (effectiveName ? effectiveName : getName(context.program, type));
929
+ if (
930
+ !overridedModelName &&
931
+ type.templateMapper &&
932
+ type.templateMapper.args &&
933
+ type.templateMapper.args.length > 0 &&
934
+ getPagedResult(context.program, type)
935
+ ) {
936
+ modelName =
937
+ type.templateMapper.args
938
+ .map((it) => {
939
+ switch (it.kind) {
940
+ case "Model":
941
+ return it.name;
942
+ case "String":
943
+ return it.value;
944
+ default:
945
+ return "";
946
+ }
947
+ })
948
+ .join("") + "List";
949
+ }
950
+
902
951
  return {
903
952
  type: "model",
904
953
  name: modelName,
@@ -1000,9 +1049,10 @@ function emitStdScalar(
1000
1049
  program: Program,
1001
1050
  scalar: Scalar & { name: IntrinsicScalarName }
1002
1051
  ): Record<string, any> {
1052
+ const newScalar = applyEncoding(program, scalar, scalar);
1003
1053
  switch (scalar.name) {
1004
1054
  case "bytes":
1005
- return { type: "byte-array", format: getEncode(program, scalar) };
1055
+ return { type: "byte-array", format: newScalar.format };
1006
1056
  case "int8":
1007
1057
  case "int16":
1008
1058
  case "int32":
@@ -1024,13 +1074,15 @@ function emitStdScalar(
1024
1074
  case "boolean":
1025
1075
  return { type: "boolean" };
1026
1076
  case "plainDate":
1027
- return { type: "date" };
1077
+ return { type: "datetime", format: newScalar.format ?? "date" };
1028
1078
  case "utcDateTime":
1029
- return { type: "datetime", format: "date-time" };
1079
+ return { type: "datetime", format: newScalar.format };
1030
1080
  case "plainTime":
1031
- return { type: "time" };
1081
+ return { type: "datetime", format: newScalar.format ?? "time" };
1082
+ case "offsetDateTime":
1083
+ return { type: "string" };
1032
1084
  case "duration":
1033
- return { type: "duration" };
1085
+ return { type: "duration", format: newScalar.format };
1034
1086
  case "numeric":
1035
1087
  return {}; // Waiting on design for more precise type https://github.com/microsoft/cadl/issues/1260
1036
1088
  default:
@@ -1038,12 +1090,51 @@ function emitStdScalar(
1038
1090
  }
1039
1091
  }
1040
1092
 
1093
+ function applyEncoding(
1094
+ program: Program,
1095
+ typespecType: Scalar | ModelProperty,
1096
+ target: any = {}
1097
+ ) {
1098
+ const encodeData = getEncode(program, typespecType);
1099
+ const formatData = getFormat(program, typespecType);
1100
+ formatData;
1101
+ if (encodeData) {
1102
+ const newTarget = { ...target };
1103
+ const newType = emitScalar(program, encodeData.type);
1104
+ // newTarget["type"] = newType["type"];
1105
+ // If the target already has a format it takes priority. (e.g. int32)
1106
+ newTarget["format"] = mergeFormatAndEncoding(
1107
+ newTarget.format,
1108
+ encodeData.encoding,
1109
+ newType["format"]
1110
+ );
1111
+ return newTarget;
1112
+ }
1113
+ return target;
1114
+ }
1115
+
1116
+ function mergeFormatAndEncoding(
1117
+ format: string | undefined,
1118
+ encoding: string,
1119
+ encodeAsFormat: string | undefined
1120
+ ): string {
1121
+ switch (format) {
1122
+ case undefined:
1123
+ return encodeAsFormat ?? encoding;
1124
+ case "date-time":
1125
+ return encoding;
1126
+ case "duration":
1127
+ default:
1128
+ return encodeAsFormat ?? encoding;
1129
+ }
1130
+ }
1131
+
1041
1132
  function applyIntrinsicDecorators(
1042
1133
  program: Program,
1043
1134
  type: Scalar | ModelProperty,
1044
1135
  result: any
1045
1136
  ): Record<string, any> {
1046
- const newResult = { ...result };
1137
+ let newResult = { ...result };
1047
1138
  const docStr = getDoc(program, type);
1048
1139
  const isString = isStringType(program, getPropertyType(type));
1049
1140
  const isNumeric = isNumericType(program, getPropertyType(type));
@@ -1052,10 +1143,7 @@ function applyIntrinsicDecorators(
1052
1143
  newResult.description = docStr;
1053
1144
  }
1054
1145
 
1055
- const formatStr = getFormat(program, type);
1056
- if (isString && !result.format && formatStr) {
1057
- newResult.format = formatStr;
1058
- }
1146
+ newResult = applyEncoding(program, type, newResult);
1059
1147
 
1060
1148
  const pattern = getPattern(program, type);
1061
1149
  if (isString && !result.pattern && pattern) {
@@ -1096,7 +1184,8 @@ function applyIntrinsicDecorators(
1096
1184
 
1097
1185
  function emitScalar(program: Program, scalar: Scalar): Record<string, any> {
1098
1186
  let result: Record<string, any> = {};
1099
- if (program.checker.isStdType(scalar)) {
1187
+ const isStd = program.checker.isStdType(scalar);
1188
+ if (isStd) {
1100
1189
  result = emitStdScalar(program, scalar);
1101
1190
  } else if (scalar.baseScalar) {
1102
1191
  result = emitScalar(program, scalar.baseScalar);
@@ -1127,7 +1216,7 @@ function emitListOrDict(
1127
1216
  return undefined;
1128
1217
  }
1129
1218
 
1130
- function mapCadlType(context: SdkContext, type: Type): any {
1219
+ function mapTypeSpecType(context: SdkContext, type: Type): any {
1131
1220
  switch (type.kind) {
1132
1221
  case "Number":
1133
1222
  return constantType(type.value, intOrFloat(type.value));
@@ -1228,7 +1317,7 @@ function emitType(context: SdkContext, type: EmitterType): Record<string, any> {
1228
1317
  if (type.kind === "CredentialTypeUnion") {
1229
1318
  return emitCredentialUnion(type);
1230
1319
  }
1231
- const builtinType = mapCadlType(context, type);
1320
+ const builtinType = mapTypeSpecType(context, type);
1232
1321
  if (builtinType !== undefined) {
1233
1322
  // add in description elements for types derived from primitive types (SecureString, etc.)
1234
1323
  const doc = getDoc(context.program, type);
@@ -1288,9 +1377,38 @@ function emitOperationGroups(
1288
1377
  operations: clientOperations
1289
1378
  });
1290
1379
  }
1380
+ resolveConflictIfExist(operationGroups);
1291
1381
  return operationGroups;
1292
1382
  }
1293
1383
 
1384
+ function resolveConflictIfExist(operationGroups: OperationGroup[]) {
1385
+ if (operationGroups.length < 2) {
1386
+ return;
1387
+ }
1388
+
1389
+ const nameSet = new Set<string>();
1390
+ const hasConflict = operationGroups.some((g) =>
1391
+ g.operations.some((op) => {
1392
+ if (nameSet.has(op.name)) {
1393
+ return true;
1394
+ } else {
1395
+ nameSet.add(op.name);
1396
+ return false;
1397
+ }
1398
+ })
1399
+ );
1400
+ if (!hasConflict) {
1401
+ return;
1402
+ }
1403
+ // Append operation group prefix
1404
+ operationGroups.forEach((g) =>
1405
+ g.operations.forEach((op) => {
1406
+ op.oriName = op.name;
1407
+ op.name = `${g.propertyName}_${op.name}`;
1408
+ })
1409
+ );
1410
+ }
1411
+
1294
1412
  function getServerHelper(
1295
1413
  program: Program,
1296
1414
  namespace: Namespace
@@ -1468,7 +1586,8 @@ function emitClients(
1468
1586
  operationGroups: emitOperationGroups(context, client, rlcModels),
1469
1587
  url: server ? server.url : "",
1470
1588
  apiVersions: [],
1471
- rlcClientName: rlcModels ? getClientName(rlcModels) : client.name
1589
+ rlcClientName: rlcModels ? getClientName(rlcModels) : client.name,
1590
+ subfolder: ""
1472
1591
  };
1473
1592
  const emittedApiVersionParam = getApiVersionParameter(context);
1474
1593
  if (emittedApiVersionParam) {
@@ -1501,23 +1620,28 @@ function getNamespaces(context: SdkContext): Set<string> {
1501
1620
  }
1502
1621
 
1503
1622
  export function emitCodeModel(
1504
- context: EmitContext<EmitterOptions>,
1623
+ dpgContext: SdkContext,
1505
1624
  rlcModelsMap: Map<string, RLCModel>,
1625
+ modularSourcesRoot: string,
1626
+ project: Project,
1506
1627
  options: { casing: "snake" | "camel" } = { casing: "snake" }
1507
1628
  ): ModularCodeModel {
1508
1629
  CASING = options.casing ?? CASING;
1509
- const dpgContext = createSdkContext(context);
1510
1630
  const clientNamespaceString =
1511
1631
  getClientNamespaceString(dpgContext)?.toLowerCase();
1512
1632
  // Get types
1513
1633
  const codeModel: ModularCodeModel = {
1514
- options: transformRLCOptions(context.options as any, dpgContext),
1634
+ options: dpgContext.rlcOptions ?? {},
1635
+ modularOptions: { sourceRoot: modularSourcesRoot },
1515
1636
  namespace: clientNamespaceString,
1516
1637
  subnamespaceToClients: {},
1517
1638
  clients: [],
1518
- types: []
1639
+ types: [],
1640
+ project
1519
1641
  };
1520
1642
 
1643
+ typesMap.clear();
1644
+ simpleTypesMap.clear();
1521
1645
  const allModels = getAllModels(dpgContext);
1522
1646
  for (const model of allModels) {
1523
1647
  getType(dpgContext, model);
@@ -1526,12 +1650,25 @@ export function emitCodeModel(
1526
1650
  for (const namespace of getNamespaces(dpgContext)) {
1527
1651
  if (namespace === clientNamespaceString) {
1528
1652
  codeModel.clients = emitClients(dpgContext, namespace, rlcModelsMap);
1653
+ codeModel.clients.length > 1 &&
1654
+ codeModel.clients.map((client) => {
1655
+ client["subfolder"] = normalizeName(
1656
+ client.name.replace("Client", ""),
1657
+ NameType.File
1658
+ );
1659
+ });
1529
1660
  } else {
1530
1661
  codeModel["subnamespaceToClients"][namespace] = emitClients(
1531
1662
  dpgContext,
1532
1663
  namespace,
1533
1664
  rlcModelsMap
1534
1665
  );
1666
+ codeModel["subnamespaceToClients"][namespace].length > 1 &&
1667
+ (codeModel["subnamespaceToClients"][namespace] as HrlcClient[]).map(
1668
+ (client) => {
1669
+ client["subfolder"] = normalizeName(client.name, NameType.File);
1670
+ }
1671
+ );
1535
1672
  }
1536
1673
  }
1537
1674
 
@@ -7,7 +7,7 @@ import {
7
7
  getDeserializePrivateFunction,
8
8
  getOperationOptionsName
9
9
  } from "./helpers/operationHelpers.js";
10
- import { Client, Operation } from "./modularCodeModel.js";
10
+ import { Client, ModularCodeModel, Operation } from "./modularCodeModel.js";
11
11
  import { isRLCMultiEndpoint } from "../utils/clientUtils.js";
12
12
  import { getDocsFromDescription } from "./helpers/docsHelpers.js";
13
13
  import { SdkContext } from "../utils/interfaces.js";
@@ -19,12 +19,11 @@ import { SdkContext } from "../utils/interfaces.js";
19
19
  */
20
20
  export function buildOperationFiles(
21
21
  dpgContext: SdkContext,
22
+ codeModel: ModularCodeModel,
22
23
  client: Client,
23
- project: Project,
24
- srcPath: string = "src",
25
- subfolder: string = "",
26
24
  needUnexpectedHelper: boolean = true
27
25
  ) {
26
+ const operationFiles = [];
28
27
  for (const operationGroup of client.operationGroups) {
29
28
  const importSet: Map<string, Set<string>> = new Map<string, Set<string>>();
30
29
  const fileName = operationGroup.className
@@ -33,7 +32,9 @@ export function buildOperationFiles(
33
32
  // into a nameless operation group. We'll call this operations.
34
33
  "operations";
35
34
 
36
- const operationGroupFile = project.createSourceFile(
35
+ const subfolder = client.subfolder;
36
+ const srcPath = codeModel.modularOptions.sourceRoot;
37
+ const operationGroupFile = codeModel.project.createSourceFile(
37
38
  `${srcPath}/${
38
39
  subfolder && subfolder !== "" ? subfolder + "/" : ""
39
40
  }api/${fileName}.ts`
@@ -41,7 +42,7 @@ export function buildOperationFiles(
41
42
 
42
43
  // Import models used from ./models.ts
43
44
  // We SHOULD keep this because otherwise ts-morph will "helpfully" try to import models from the rest layer when we call fixMissingImports().
44
- importModels(srcPath, operationGroupFile, project, subfolder);
45
+ importModels(srcPath, operationGroupFile, codeModel.project, subfolder);
45
46
 
46
47
  const namedImports: string[] = [];
47
48
  let clientType = "Client";
@@ -114,7 +115,9 @@ export function buildOperationFiles(
114
115
  operationGroupFile.fixMissingImports();
115
116
  // have to fixUnusedIdentifiers after everything get generated.
116
117
  operationGroupFile.fixUnusedIdentifiers();
118
+ operationFiles.push(operationGroupFile);
117
119
  }
120
+ return operationFiles;
118
121
  }
119
122
 
120
123
  export function importModels(
@@ -134,10 +137,12 @@ export function importModels(
134
137
  models.push(entry[0]);
135
138
  }
136
139
 
137
- sourceFile.addImportDeclaration({
138
- moduleSpecifier: "../models/models.js",
139
- namedImports: models
140
- });
140
+ if (models.length > 0) {
141
+ sourceFile.addImportDeclaration({
142
+ moduleSpecifier: "../models/models.js",
143
+ namedImports: models
144
+ });
145
+ }
141
146
 
142
147
  // Import all models and then let ts-morph clean up the unused ones
143
148
  // we can't fixUnusedIdentifiers here because the operaiton files are still being generated.
@@ -169,7 +174,7 @@ export function buildOperationOptions(
169
174
  return {
170
175
  docs: getDocsFromDescription(p.description),
171
176
  hasQuestionToken: true,
172
- ...buildType(p.clientName, p.type)
177
+ ...buildType(p.clientName, p.type, p.format)
173
178
  };
174
179
  })
175
180
  });
@@ -100,7 +100,7 @@ export function emitPackage(
100
100
  generateSample
101
101
  )}`,
102
102
  clean:
103
- "rimraf dist dist-browser dist-esm test-dist temp types *.tgz *.log",
103
+ "rimraf --glob dist dist-browser dist-esm test-dist temp types *.tgz *.log",
104
104
  "execute:samples": "echo skipped",
105
105
  "extract-api":
106
106
  "rimraf review && mkdirp ./review && api-extractor run --local",
@@ -156,7 +156,7 @@ export function emitPackage(
156
156
  eslint: "^8.0.0",
157
157
  mkdirp: "^2.1.2",
158
158
  prettier: "^2.5.1",
159
- rimraf: "^3.0.0",
159
+ rimraf: "^5.0.0",
160
160
  "source-map-support": "^0.5.9",
161
161
  typescript: "~5.0.0"
162
162
  }