@azure-tools/typespec-ts 0.15.0 → 0.16.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 (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 +141 -54
  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 +140 -77
  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 +183 -60
  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 +231 -118
  89. package/src/modular/helpers/typeHelpers.ts +14 -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
@@ -1,11 +1,17 @@
1
1
  import { OperationResponse, RLCOptions } from "@azure-tools/rlc-common";
2
+ import { Project } from "ts-morph";
2
3
 
4
+ export interface ModularOptions {
5
+ sourceRoot: string;
6
+ }
3
7
  export interface ModularCodeModel {
4
8
  options: RLCOptions;
9
+ modularOptions: ModularOptions;
5
10
  namespace?: string;
6
11
  subnamespaceToClients?: any;
7
12
  clients: Client[];
8
13
  types: Type[];
14
+ project: Project;
9
15
  }
10
16
 
11
17
  export interface Header {
@@ -21,6 +27,7 @@ export interface Property {
21
27
  optional?: boolean;
22
28
  description: string;
23
29
  readonly?: boolean;
30
+ format?: string;
24
31
  }
25
32
 
26
33
  export interface BodyParameter {
@@ -81,6 +88,7 @@ export interface Type {
81
88
  isFixed?: boolean;
82
89
  valueType?: Type;
83
90
  elementType?: Type;
91
+ parents?: Type[];
84
92
  xmlMetadata?: XmlMetadata;
85
93
  format?: string;
86
94
  properties?: Property[];
@@ -96,6 +104,7 @@ export interface Client {
96
104
  url: string;
97
105
  apiVersions: any[];
98
106
  rlcClientName: string;
107
+ subfolder?: string;
99
108
  }
100
109
 
101
110
  export type ParameterLocation =
@@ -124,6 +133,7 @@ export interface Parameter {
124
133
  inDocstring?: boolean;
125
134
  inOverriden?: boolean;
126
135
  isApiVersion?: boolean;
136
+ format?: string;
127
137
  }
128
138
 
129
139
  export interface Response {
@@ -136,6 +146,7 @@ export interface Response {
136
146
 
137
147
  export interface Operation {
138
148
  name: string;
149
+ oriName?: string;
139
150
  description: string;
140
151
  summary: string;
141
152
  url: string;
@@ -10,9 +10,9 @@ import { getHttpOperation, HttpOperation } from "@typespec/http";
10
10
  import {
11
11
  hasPagingOperations,
12
12
  extractPagedMetadataNested,
13
- hasPollingOperations
13
+ hasPollingOperations,
14
+ getSpecialSerializeInfo
14
15
  } from "../utils/operationUtil.js";
15
- import { getSpecialSerializeInfo } from "./transformParameters.js";
16
16
  import { SdkContext } from "../utils/interfaces.js";
17
17
 
18
18
  export function transformHelperFunctionDetails(
@@ -199,7 +199,10 @@ function extractSpecialSerializeInfo(
199
199
  for (const op of operations) {
200
200
  const route = ignoreDiagnostics(getHttpOperation(program, op));
201
201
  route.parameters.parameters.forEach((parameter) => {
202
- const serializeInfo = getSpecialSerializeInfo(parameter);
202
+ const serializeInfo = getSpecialSerializeInfo(
203
+ parameter.type,
204
+ (parameter as any).format
205
+ );
203
206
  hasMultiCollection = hasMultiCollection
204
207
  ? hasMultiCollection
205
208
  : serializeInfo.hasMultiCollection;
@@ -222,7 +225,10 @@ function extractSpecialSerializeInfo(
222
225
  for (const clientOp of clientOperations) {
223
226
  const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
224
227
  route.parameters.parameters.forEach((parameter) => {
225
- const serializeInfo = getSpecialSerializeInfo(parameter);
228
+ const serializeInfo = getSpecialSerializeInfo(
229
+ parameter.type,
230
+ (parameter as any).format
231
+ );
226
232
  hasMultiCollection = hasMultiCollection
227
233
  ? hasMultiCollection
228
234
  : serializeInfo.hasMultiCollection;
@@ -31,6 +31,7 @@ import {
31
31
  import {
32
32
  getOperationGroupName,
33
33
  getOperationName,
34
+ getSpecialSerializeInfo,
34
35
  isBinaryPayload
35
36
  } from "../utils/operationUtil.js";
36
37
  import {
@@ -140,7 +141,10 @@ function getParameterMetadata(
140
141
  type === "number[]" ||
141
142
  type === "Array<number>"
142
143
  ) {
143
- const serializeInfo = getSpecialSerializeInfo(parameter);
144
+ const serializeInfo = getSpecialSerializeInfo(
145
+ parameter.type,
146
+ (parameter as any).format
147
+ );
144
148
  if (
145
149
  serializeInfo.hasMultiCollection ||
146
150
  serializeInfo.hasPipeCollection ||
@@ -279,7 +283,7 @@ function transformNormalBody(
279
283
  if (hasBinaryContent) {
280
284
  descriptions.push("Value may contain any sequence of octets");
281
285
  }
282
- const type = extractNameFromCadlType(
286
+ const type = extractNameFromTypeSpecType(
283
287
  dpgContext,
284
288
  bodyType,
285
289
  importedModels,
@@ -315,7 +319,11 @@ function transformMultiFormBody(
315
319
  const isModelBody = bodyType.kind === "Model";
316
320
 
317
321
  if (!isModelBody) {
318
- const type = extractNameFromCadlType(dpgContext, bodyType, importedModels);
322
+ const type = extractNameFromTypeSpecType(
323
+ dpgContext,
324
+ bodyType,
325
+ importedModels
326
+ );
319
327
  const description = extractDescriptionsFromBody(
320
328
  dpgContext,
321
329
  bodyType,
@@ -357,7 +365,7 @@ function transformMultiFormBody(
357
365
  SchemaContext.Exception
358
366
  ])}>`;
359
367
  } else {
360
- type = extractNameFromCadlType(
368
+ type = extractNameFromTypeSpecType(
361
369
  dpgContext,
362
370
  paramType.type,
363
371
  importedModels
@@ -388,13 +396,13 @@ function getBodyDetail(
388
396
  return { hasBinaryContent, hasFormContent };
389
397
  }
390
398
 
391
- function extractNameFromCadlType(
399
+ function extractNameFromTypeSpecType(
392
400
  dpgContext: SdkContext,
393
- cadlType: Type,
401
+ type: Type,
394
402
  importedModels: Set<string>,
395
403
  headers?: ParameterMetadata[]
396
404
  ) {
397
- const bodySchema = getSchemaForType(dpgContext, cadlType, [
405
+ const bodySchema = getSchemaForType(dpgContext, type, [
398
406
  SchemaContext.Input,
399
407
  SchemaContext.Exception
400
408
  ]) as Schema;
@@ -470,53 +478,3 @@ function extractDescriptionsFromBody(
470
478
  );
471
479
  return description ? [description] : [];
472
480
  }
473
-
474
- export function getSpecialSerializeInfo(parameter: HttpOperationParameter) {
475
- let hasMultiCollection = false;
476
- let hasPipeCollection = false;
477
- let hasSsvCollection = false;
478
- let hasTsvCollection = false;
479
- let hasCsvCollection = false;
480
- const descriptions = [];
481
- const collectionInfo = [];
482
- if (
483
- (parameter.type === "query" || parameter.type === "header") &&
484
- (parameter as any).format === "multi"
485
- ) {
486
- hasMultiCollection = true;
487
- descriptions.push("buildMultiCollection");
488
- collectionInfo.push("multi");
489
- }
490
- if (parameter.type === "query" && (parameter as any).format === "ssv") {
491
- hasSsvCollection = true;
492
- descriptions.push("buildSsvCollection");
493
- collectionInfo.push("ssv");
494
- }
495
-
496
- if (parameter.type === "query" && (parameter as any).format === "tsv") {
497
- hasTsvCollection = true;
498
- descriptions.push("buildTsvCollection");
499
- collectionInfo.push("tsv");
500
- }
501
-
502
- if (parameter.type === "query" && (parameter as any).format === "pipes") {
503
- hasPipeCollection = true;
504
- descriptions.push("buildPipeCollection");
505
- collectionInfo.push("pipe");
506
- }
507
-
508
- if (parameter.type === "header" && (parameter as any).format === "csv") {
509
- hasCsvCollection = true;
510
- descriptions.push("buildCsvCollection");
511
- collectionInfo.push("csv");
512
- }
513
- return {
514
- hasMultiCollection,
515
- hasPipeCollection,
516
- hasSsvCollection,
517
- hasTsvCollection,
518
- hasCsvCollection,
519
- descriptions,
520
- collectionInfo
521
- };
522
- }
@@ -182,12 +182,10 @@ function transformBody(
182
182
  const bodySchema = getSchemaForType(dpgContext, body!.type, [
183
183
  SchemaContext.Output
184
184
  ]) as Schema;
185
- if (bodySchema.fromCore) {
186
- fromCore = true;
187
- }
185
+ fromCore = bodySchema.fromCore ?? false;
188
186
  const bodyType = getTypeName(bodySchema);
189
187
  const importedNames = getImportedModelName(bodySchema);
190
- if (importedNames) {
188
+ if (importedNames && !fromCore) {
191
189
  importedNames
192
190
  .filter((name) => {
193
191
  return name !== "any";
@@ -13,7 +13,8 @@ import {
13
13
  getSchemaForType,
14
14
  includeDerivedModel,
15
15
  getBodyType,
16
- trimUsage
16
+ trimUsage,
17
+ isAzureCoreErrorType
17
18
  } from "../utils/modelUtils.js";
18
19
  import { SdkContext } from "../utils/interfaces.js";
19
20
 
@@ -61,12 +62,7 @@ export function transformSchemas(
61
62
  getGeneratedModels(bodyModel, SchemaContext.Input);
62
63
  }
63
64
  for (const resp of route.responses) {
64
- if (
65
- resp.type.kind === "Model" &&
66
- resp.type.name === "ErrorResponse" &&
67
- resp.type.namespace?.name === "Foundations" &&
68
- resp.type.namespace.namespace?.name === "Core"
69
- ) {
65
+ if (isAzureCoreErrorType(resp.type)) {
70
66
  continue;
71
67
  }
72
68
  for (const resps of resp.responses) {
@@ -78,8 +74,8 @@ export function transformSchemas(
78
74
  }
79
75
  }
80
76
  }
81
- program.stateMap(modelKey).forEach((context, cadlModel) => {
82
- const model = getSchemaForType(dpgContext, cadlModel, context);
77
+ program.stateMap(modelKey).forEach((context, tspModel) => {
78
+ const model = getSchemaForType(dpgContext, tspModel, context);
83
79
  if (model) {
84
80
  model.usage = context;
85
81
  }
@@ -6,7 +6,8 @@ import {
6
6
  listOperationsInOperationGroup
7
7
  } from "@azure-tools/typespec-client-generator-core";
8
8
  import { ignoreDiagnostics } from "@typespec/compiler";
9
- import { getHttpOperation, HttpOperation } from "@typespec/http";
9
+ import { getCustomRequestHeaderNameForOperation } from "../utils/operationUtil.js";
10
+ import { getHttpOperation } from "@typespec/http";
10
11
 
11
12
  export function transformTelemetryInfo(
12
13
  dpgContext: SdkContext,
@@ -39,7 +40,7 @@ function getCustomRequestHeaderNameForClient(
39
40
  const headerName = getCustomRequestHeaderNameForOperation(
40
41
  ignoreDiagnostics(getHttpOperation(program, op))
41
42
  );
42
- if (headerName != undefined) {
43
+ if (headerName !== undefined) {
43
44
  return headerName;
44
45
  }
45
46
  }
@@ -49,24 +50,9 @@ function getCustomRequestHeaderNameForClient(
49
50
  const headerName = getCustomRequestHeaderNameForOperation(
50
51
  ignoreDiagnostics(getHttpOperation(program, clientOp))
51
52
  );
52
- if (headerName != undefined) {
53
+ if (headerName !== undefined) {
53
54
  return headerName;
54
55
  }
55
56
  }
56
57
  return undefined;
57
58
  }
58
-
59
- function getCustomRequestHeaderNameForOperation(
60
- route: HttpOperation
61
- ): string | undefined {
62
- const CUSTOM_REQUEST_HEADER_NAME = "client-request-id";
63
- const params = route.parameters.parameters.filter(
64
- (p) =>
65
- p.type === "header" && p.name.toLowerCase() === CUSTOM_REQUEST_HEADER_NAME
66
- );
67
- if (params.length > 0) {
68
- return CUSTOM_REQUEST_HEADER_NAME;
69
- }
70
-
71
- return undefined;
72
- }
@@ -5,12 +5,22 @@ import {
5
5
  RLCOptions,
6
6
  ServiceInfo
7
7
  } from "@azure-tools/rlc-common";
8
- import { getDoc, NoTarget, Program } from "@typespec/compiler";
9
- import { getAuthentication } from "@typespec/http";
8
+ import {
9
+ getDoc,
10
+ ignoreDiagnostics,
11
+ NoTarget,
12
+ Program
13
+ } from "@typespec/compiler";
14
+ import { getAuthentication, getHttpOperation } from "@typespec/http";
10
15
  import { reportDiagnostic } from "../lib.js";
11
16
  import { getDefaultService } from "../utils/modelUtils.js";
12
17
  import { getRLCClients } from "../utils/clientUtils.js";
13
18
  import { SdkContext } from "../utils/interfaces.js";
19
+ import {
20
+ listOperationGroups,
21
+ listOperationsInOperationGroup
22
+ } from "@azure-tools/typespec-client-generator-core";
23
+ import { getOperationName } from "../utils/operationUtil.js";
14
24
 
15
25
  export function transformRLCOptions(
16
26
  emitterOptions: RLCOptions,
@@ -18,7 +28,7 @@ export function transformRLCOptions(
18
28
  ): RLCOptions {
19
29
  // Extract the options from emitter option
20
30
  const options = extractRLCOptions(
21
- dpgContext.program,
31
+ dpgContext,
22
32
  emitterOptions,
23
33
  dpgContext.generationPathDetail?.rootDir ?? ""
24
34
  );
@@ -28,10 +38,11 @@ export function transformRLCOptions(
28
38
  }
29
39
 
30
40
  function extractRLCOptions(
31
- program: Program,
41
+ dpgContext: SdkContext,
32
42
  emitterOptions: RLCOptions,
33
43
  generationRootDir: string
34
44
  ): RLCOptions {
45
+ const program = dpgContext.program;
35
46
  const includeShortcuts = getIncludeShortcuts(emitterOptions);
36
47
  const packageDetails = getPackageDetails(program, emitterOptions);
37
48
  const serviceInfo = getServiceInfo(program);
@@ -41,7 +52,10 @@ function extractRLCOptions(
41
52
  const generateTest: undefined | boolean = getGenerateTest(emitterOptions);
42
53
  const credentialInfo = getCredentialInfo(program, emitterOptions);
43
54
  const azureOutputDirectory = getAzureOutputDirectory(generationRootDir);
44
- const enableOperationGroup = getEnableOperationGroup(emitterOptions);
55
+ const enableOperationGroup = getEnableOperationGroup(
56
+ dpgContext,
57
+ emitterOptions
58
+ );
45
59
  return {
46
60
  ...emitterOptions,
47
61
  ...credentialInfo,
@@ -52,7 +66,7 @@ function extractRLCOptions(
52
66
  azureSdkForJs,
53
67
  serviceInfo,
54
68
  azureOutputDirectory,
55
- sourceFrom: "Cadl",
69
+ sourceFrom: "TypeSpec",
56
70
  enableOperationGroup
57
71
  };
58
72
  }
@@ -112,10 +126,54 @@ function processAuth(program: Program) {
112
126
  return securityInfo;
113
127
  }
114
128
 
115
- function getEnableOperationGroup(emitterOptions: RLCOptions) {
116
- if (emitterOptions.enableOperationGroup === true) {
117
- return true;
129
+ function getEnableOperationGroup(
130
+ dpgContext: SdkContext,
131
+ emitterOptions: RLCOptions
132
+ ) {
133
+ if (
134
+ emitterOptions.enableOperationGroup === true ||
135
+ emitterOptions.enableOperationGroup === false
136
+ ) {
137
+ return emitterOptions.enableOperationGroup;
118
138
  }
139
+ // Detect if existing name conflicts if customers didn't set the option explicitly
140
+ return detectIfNameConflicts(dpgContext);
141
+ }
142
+
143
+ function detectIfNameConflicts(dpgContext: SdkContext) {
144
+ const clients = getRLCClients(dpgContext);
145
+ const program = dpgContext.program;
146
+ const nameSet = new Set<string>();
147
+ for (const client of clients) {
148
+ const operationGroups = listOperationGroups(dpgContext, client);
149
+ for (const operationGroup of operationGroups) {
150
+ const operations = listOperationsInOperationGroup(
151
+ dpgContext,
152
+ operationGroup
153
+ );
154
+ for (const op of operations) {
155
+ const route = ignoreDiagnostics(getHttpOperation(program, op));
156
+ const name = getOperationName(program, route.operation);
157
+ if (nameSet.has(name)) {
158
+ return true;
159
+ } else {
160
+ nameSet.add(name);
161
+ }
162
+ }
163
+ }
164
+ const clientOperations = listOperationsInOperationGroup(dpgContext, client);
165
+ for (const clientOp of clientOperations) {
166
+ const route = ignoreDiagnostics(getHttpOperation(program, clientOp));
167
+ const name = getOperationName(program, route.operation);
168
+ if (nameSet.has(name)) {
169
+ return true;
170
+ } else {
171
+ nameSet.add(name);
172
+ }
173
+ }
174
+ }
175
+
176
+ // No conflicts if we didn't detect any
119
177
  return false;
120
178
  }
121
179