@azure-tools/typespec-ts 0.38.3 → 0.38.4-alpha.20250307.2

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 (51) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +16 -16
  3. package/dist/src/index.d.ts.map +1 -1
  4. package/dist/src/index.js +10 -8
  5. package/dist/src/index.js.map +1 -1
  6. package/dist/src/lib.d.ts +71 -2
  7. package/dist/src/lib.d.ts.map +1 -1
  8. package/dist/src/lib.js +108 -1
  9. package/dist/src/lib.js.map +1 -1
  10. package/dist/src/modular/buildClientContext.js +1 -1
  11. package/dist/src/modular/buildClientContext.js.map +1 -1
  12. package/dist/src/modular/emitModels.d.ts +1 -1
  13. package/dist/src/modular/emitModels.d.ts.map +1 -1
  14. package/dist/src/modular/emitModels.js +25 -7
  15. package/dist/src/modular/emitModels.js.map +1 -1
  16. package/dist/src/modular/emitSamples.js +1 -1
  17. package/dist/src/modular/emitSamples.js.map +1 -1
  18. package/dist/src/modular/helpers/classicalOperationHelpers.d.ts.map +1 -1
  19. package/dist/src/modular/helpers/classicalOperationHelpers.js +1 -1
  20. package/dist/src/modular/helpers/classicalOperationHelpers.js.map +1 -1
  21. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  22. package/dist/src/modular/helpers/operationHelpers.js +44 -20
  23. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  24. package/dist/src/modular/static-helpers-metadata.d.ts +7 -0
  25. package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
  26. package/dist/src/modular/static-helpers-metadata.js +7 -0
  27. package/dist/src/modular/static-helpers-metadata.js.map +1 -1
  28. package/dist/src/transform/transform.d.ts.map +1 -1
  29. package/dist/src/transform/transform.js +4 -0
  30. package/dist/src/transform/transform.js.map +1 -1
  31. package/dist/src/transform/transfromRLCOptions.d.ts +4 -0
  32. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  33. package/dist/src/transform/transfromRLCOptions.js +283 -29
  34. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  35. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  36. package/dist/src/utils/operationUtil.js +2 -4
  37. package/dist/src/utils/operationUtil.js.map +1 -1
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +23 -23
  40. package/src/index.ts +11 -4
  41. package/src/lib.ts +167 -2
  42. package/src/modular/buildClientContext.ts +5 -1
  43. package/src/modular/emitModels.ts +42 -10
  44. package/src/modular/emitSamples.ts +1 -1
  45. package/src/modular/helpers/classicalOperationHelpers.ts +5 -4
  46. package/src/modular/helpers/operationHelpers.ts +66 -30
  47. package/src/modular/static-helpers-metadata.ts +7 -0
  48. package/src/transform/transform.ts +4 -0
  49. package/src/transform/transfromRLCOptions.ts +340 -41
  50. package/src/utils/operationUtil.ts +2 -4
  51. package/static/static-helpers/urlTemplate.ts +196 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-tools/typespec-ts",
3
- "version": "0.38.3",
3
+ "version": "0.38.4-alpha.20250307.2",
4
4
  "description": "An experimental TypeSpec emitter for TypeScript RLC",
5
5
  "main": "dist/src/index.js",
6
6
  "type": "module",
@@ -18,14 +18,14 @@
18
18
  "license": "MIT",
19
19
  "devDependencies": {
20
20
  "@azure-rest/core-client": "^2.3.1",
21
- "@typespec/http-specs": "0.1.0-alpha.9",
22
- "@typespec/spector": "0.1.0-alpha.7",
23
- "@typespec/spec-api": "0.1.0-alpha.0",
24
- "@azure-tools/azure-http-specs": "0.1.0-alpha.6",
25
- "@azure-tools/typespec-autorest": ">=0.51.0 <1.0.0",
26
- "@azure-tools/typespec-azure-core": ">=0.51.0 <1.0.0",
27
- "@azure-tools/typespec-azure-resource-manager": ">=0.51.0 <1.0.0",
28
- "@azure-tools/typespec-client-generator-core": ">=0.51.3 <1.0.0",
21
+ "@typespec/http-specs": "0.1.0-alpha.11",
22
+ "@typespec/spector": "0.1.0-alpha.8",
23
+ "@typespec/spec-api": "0.1.0-alpha.1",
24
+ "@azure-tools/azure-http-specs": "0.1.0-alpha.7",
25
+ "@azure-tools/typespec-autorest": ">=0.52.0 <1.0.0",
26
+ "@azure-tools/typespec-azure-core": ">=0.52.0 <1.0.0",
27
+ "@azure-tools/typespec-azure-resource-manager": ">=0.52.0 <1.0.0",
28
+ "@azure-tools/typespec-client-generator-core": ">=0.52.0 <1.0.0",
29
29
  "@azure/abort-controller": "^2.1.2",
30
30
  "@azure/core-auth": "^1.6.0",
31
31
  "@azure/core-lro": "^3.1.0",
@@ -40,12 +40,12 @@
40
40
  "@types/node": "^18.0.0",
41
41
  "@typescript-eslint/eslint-plugin": "^6.8.0",
42
42
  "@typescript-eslint/parser": "^6.8.0",
43
- "@typespec/compiler": ">=0.65.2 <1.0.0",
44
- "@typespec/http": ">=0.65.0 <1.0.0",
45
- "@typespec/openapi": ">=0.65.0, <1.0.0",
46
- "@typespec/rest": ">=0.65.0 <1.0.0",
43
+ "@typespec/compiler": ">=0.66.0 <1.0.0",
44
+ "@typespec/http": ">=0.66.0 <1.0.0",
45
+ "@typespec/openapi": ">=0.66.0, <1.0.0",
46
+ "@typespec/rest": ">=0.66.0 <1.0.0",
47
47
  "@typespec/ts-http-runtime": "0.1.0",
48
- "@typespec/versioning": ">=0.65.0 <1.0.0",
48
+ "@typespec/versioning": ">=0.66.0 <1.0.0",
49
49
  "chai": "^4.3.6",
50
50
  "chalk": "^4.0.0",
51
51
  "cross-env": "^7.0.3",
@@ -67,15 +67,15 @@
67
67
  "js-yaml": "^4.1.0"
68
68
  },
69
69
  "peerDependencies": {
70
- "@azure-tools/typespec-azure-core": ">=0.51.0 <1.0.0",
71
- "@azure-tools/typespec-client-generator-core": ">=0.51.3 <1.0.0",
72
- "@typespec/compiler": ">=0.65.2 <1.0.0",
73
- "@typespec/http": ">=0.65.0 <1.0.0",
74
- "@typespec/rest": ">=0.65.0 <1.0.0",
75
- "@typespec/versioning": ">=0.65.0 <1.0.0"
70
+ "@azure-tools/typespec-azure-core": ">=0.52.0 <1.0.0",
71
+ "@azure-tools/typespec-client-generator-core": ">=0.52.0 <1.0.0",
72
+ "@typespec/compiler": ">=0.66.0 <1.0.0",
73
+ "@typespec/http": ">=0.66.0 <1.0.0",
74
+ "@typespec/rest": ">=0.66.0 <1.0.0",
75
+ "@typespec/versioning": ">=0.66.0 <1.0.0"
76
76
  },
77
77
  "dependencies": {
78
- "@azure-tools/rlc-common": "^0.38.3",
78
+ "@azure-tools/rlc-common": "0.38.4-alpha.20250307.2",
79
79
  "fs-extra": "^11.1.0",
80
80
  "lodash": "^4.17.21",
81
81
  "prettier": "^3.3.3",
@@ -112,7 +112,7 @@
112
112
  "lint:fix": "eslint src --fix --ext .ts",
113
113
  "format": "npm run -s prettier -- --write",
114
114
  "check-format": "npm run prettier -- --check",
115
- "prettier": "prettier --config ./.prettierrc \"src/**/*.ts\"",
115
+ "prettier": "prettier --config ./.prettierrc \"(src|static|test)/**/*.!(d).ts\"",
116
116
  "check:tree": "node --loader ts-node/esm ./test/commands/check-clean-tree.ts",
117
117
  "integration-test-ci": "npm-run-all copy:typespec integration-test-ci:rlc integration-test-ci:azure-rlc integration-test-ci:modular integration-test-ci:azure-modular",
118
118
  "integration-test-ci:sequential": "npm-run-all --serial copy:typespec integration-test-ci:modular && npm run integration-test-ci:modular",
@@ -144,6 +144,6 @@
144
144
  "stop-test-server": "npx tsp-spector server stop",
145
145
  "unit-test": "npm-run-all --parallel unit-test:rlc unit-test:modular",
146
146
  "unit-test:rlc": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register --experimental-specifier-resolution=node --experimental-modules=true --timeout 36000 './test/unit/**/*.spec.ts'",
147
- "unit-test:modular": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register --experimental-specifier-resolution=node --experimental-modules=true --no-timeout './test/modularUnit/**/*.spec.ts'"
147
+ "unit-test:modular": "cross-env TS_NODE_PROJECT=tsconfig.test.json mocha -r ts-node/register --experimental-specifier-resolution=node --experimental-modules=true --no-timeout './test/modularUnit/**/*.spec.ts'"
148
148
  }
149
149
  }
package/src/index.ts CHANGED
@@ -14,7 +14,8 @@ import {
14
14
  MultipartHelpers,
15
15
  PagingHelpers,
16
16
  PollingHelpers,
17
- SerializationHelpers
17
+ SerializationHelpers,
18
+ UrlTemplateHelpers
18
19
  } from "./modular/static-helpers-metadata.js";
19
20
  import {
20
21
  RLCModel,
@@ -121,6 +122,7 @@ export async function $onEmit(context: EmitContext) {
121
122
  ...SerializationHelpers,
122
123
  ...PagingHelpers,
123
124
  ...PollingHelpers,
125
+ ...UrlTemplateHelpers,
124
126
  ...MultipartHelpers
125
127
  },
126
128
  {
@@ -323,7 +325,7 @@ export async function $onEmit(context: EmitContext) {
323
325
  );
324
326
  }
325
327
  // Enable modular sample generation when explicitly set to true or MPG
326
- if (emitterOptions?.generateSample === true) {
328
+ if (emitterOptions.generateSample === true) {
327
329
  const samples = emitSamples(dpgContext);
328
330
  // Refine the rlc sample generation logic
329
331
  // TODO: remember to remove this out when RLC is splitted from Modular
@@ -498,9 +500,11 @@ export async function createContextWithDefaultOptions(
498
500
  context: EmitContext<Record<string, any>>
499
501
  ): Promise<SdkContext> {
500
502
  const flattenUnionAsEnum =
503
+ context.options["experimental-extensible-enums"] === undefined &&
501
504
  context.options["experimentalExtensibleEnums"] === undefined
502
505
  ? isArm(context)
503
- : context.options["experimentalExtensibleEnums"];
506
+ : (context.options["experimental-extensible-enums"] ??
507
+ context.options["experimentalExtensibleEnums"]);
504
508
  const tcgcSettings = {
505
509
  "generate-protocol-methods": true,
506
510
  "generate-convenience-methods": true,
@@ -525,7 +529,10 @@ export async function createContextWithDefaultOptions(
525
529
 
526
530
  // TODO: should be removed once tcgc issue is resolved https://github.com/Azure/typespec-azure/issues/1794
527
531
  function isArm(context: EmitContext<Record<string, any>>) {
528
- const packageName = (context?.options["packageDetails"] ?? {})["name"] ?? "";
532
+ const packageName =
533
+ (context?.options["package-details"] ??
534
+ context?.options["packageDetails"] ??
535
+ {})["name"] ?? "";
529
536
  return packageName?.startsWith("@azure/arm-");
530
537
  }
531
538
 
package/src/lib.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT License.
3
3
 
4
- import { RLCOptions } from "@azure-tools/rlc-common";
4
+ import {
5
+ PackageDetails,
6
+ DependencyInfo,
7
+ ServiceInfo,
8
+ PackageFlavor,
9
+ RLCOptions
10
+ } from "@azure-tools/rlc-common";
5
11
  import {
6
12
  createTypeSpecLibrary,
7
13
  JSONSchemaType,
@@ -10,10 +16,61 @@ import {
10
16
  import { Options } from "prettier";
11
17
 
12
18
  export interface EmitterOptions extends RLCOptions {
19
+ "include-shortcuts"?: boolean;
20
+ "multi-client"?: boolean;
21
+ batch?: any[];
22
+ "package-details"?: PackageDetails;
23
+ "add-credentials"?: boolean;
24
+ /** Three possiblie values:
25
+ * - undefined, no credentialScopes and relevant settings would be generated
26
+ * - [], which means we would generate TokenCredential but no credentialScopes and relevant settings
27
+ * - ["..."], which means we would generate credentialScopes and relevant settings with the given values
28
+ */
29
+ "credential-scopes"?: string[];
30
+ "credential-key-header-name"?: string;
31
+ "custom-http-auth-header-name"?: string;
32
+ "custom-http-auth-shared-key-prefix"?: string;
33
+ /**
34
+ * Three possible values:
35
+ * - undefined, the default behavior which means we would generate metadata if the package.json file is absent
36
+ * - true, which means we would always generate new files or override existing files
37
+ * - false, which means we would not generate any files no matter there exists or not
38
+ */
39
+ "generate-metadata"?: boolean;
40
+ /**
41
+ * Three possible values:
42
+ * - undefined, the default behavior which means we would generate test if there is no `test` folder
43
+ * - true, which means we would always generate new files or override existing files
44
+ * - false, which means we would not generate any files no matter there exists or not
45
+ */
46
+ "generate-test"?: boolean;
47
+ "generate-sample"?: boolean;
48
+ "azure-sdk-for-js"?: boolean;
49
+ "azure-output-directory"?: string;
50
+ "is-typespec-test"?: boolean;
51
+ title?: string;
52
+ "dependency-info"?: DependencyInfo;
53
+ "product-doc-link"?: string;
54
+ "service-info"?: ServiceInfo;
55
+ "azure-arm"?: boolean;
56
+ "source-from"?: "TypeSpec" | "Swagger";
57
+ "is-modular-library"?: boolean;
58
+ "module-kind"?: "esm" | "cjs";
59
+ "enable-operation-group"?: boolean;
60
+ flavor?: PackageFlavor;
61
+ "enable-model-namespace"?: boolean;
62
+ "hierarchy-client"?: boolean;
63
+ "compatibility-mode"?: boolean;
64
+ "experimental-extensible-enums"?: boolean;
65
+ "clear-output-folder"?: boolean;
66
+ "ignore-property-name-normalize"?: boolean;
67
+ "compatibility-query-multi-format"?: boolean;
13
68
  branded?: boolean;
69
+ "typespec-title-map"?: Record<string, string>;
70
+ "ignore-enum-member-name-normalize"?: boolean;
14
71
  }
15
72
 
16
- export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
73
+ const _RLCOptionsSchema: JSONSchemaType<RLCOptions> = {
17
74
  type: "object",
18
75
  additionalProperties: true,
19
76
  properties: {
@@ -93,6 +150,7 @@ export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
93
150
  experimentalExtensibleEnums: { type: "boolean", nullable: true },
94
151
  clearOutputFolder: { type: "boolean", nullable: true },
95
152
  ignorePropertyNameNormalize: { type: "boolean", nullable: true },
153
+ ignoreEnumMemberNameNormalize: { type: "boolean", nullable: true },
96
154
  compatibilityQueryMultiFormat: { type: "boolean", nullable: true },
97
155
  typespecTitleMap: {
98
156
  type: "object",
@@ -106,6 +164,101 @@ export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
106
164
  required: []
107
165
  };
108
166
 
167
+ export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
168
+ type: "object",
169
+ additionalProperties: true,
170
+ properties: {
171
+ ..._RLCOptionsSchema.properties,
172
+ "include-shortcuts": { type: "boolean", nullable: true },
173
+ "multi-client": { type: "boolean", nullable: true },
174
+ batch: {
175
+ type: "array",
176
+ nullable: true,
177
+ items: {
178
+ type: "string"
179
+ }
180
+ },
181
+ "package-details": {
182
+ type: "object",
183
+ additionalProperties: true,
184
+ properties: {
185
+ name: { type: "string", nullable: false },
186
+ scopeName: { type: "string", nullable: true },
187
+ nameWithoutScope: { type: "string", nullable: true },
188
+ description: { type: "string", nullable: true },
189
+ version: { type: "string", nullable: true }
190
+ },
191
+ required: ["name"],
192
+ nullable: true
193
+ },
194
+ "add-credentials": { type: "boolean", nullable: true },
195
+ "credential-scopes": {
196
+ type: "array",
197
+ nullable: true,
198
+ items: { type: "string" }
199
+ },
200
+ "credential-key-header-name": { type: "string", nullable: true },
201
+ "custom-http-auth-header-name": { type: "string", nullable: true },
202
+ "custom-http-auth-shared-key-prefix": { type: "string", nullable: true },
203
+ "generate-metadata": { type: "boolean", nullable: true },
204
+ "generate-test": { type: "boolean", nullable: true },
205
+ "generate-sample": { type: "boolean", nullable: true },
206
+ "azure-sdk-for-js": { type: "boolean", nullable: true },
207
+ "azure-output-directory": { type: "string", nullable: true },
208
+ "is-typespec-test": { type: "boolean", nullable: true },
209
+ title: { type: "string", nullable: true },
210
+ "dependency-info": {
211
+ type: "object",
212
+ additionalProperties: true,
213
+ properties: {
214
+ link: { type: "string", nullable: false },
215
+ description: { type: "string", nullable: false }
216
+ },
217
+ required: [],
218
+ nullable: true
219
+ },
220
+ "product-doc-link": { type: "string", nullable: true },
221
+ "service-info": {
222
+ type: "object",
223
+ additionalProperties: true,
224
+ properties: {
225
+ title: { type: "string", nullable: true },
226
+ description: { type: "string", nullable: true }
227
+ },
228
+ nullable: true
229
+ },
230
+ "azure-arm": { type: "boolean", nullable: true },
231
+ "source-from": { type: "string", nullable: true },
232
+ "is-modular-library": { type: "boolean", nullable: true, default: false },
233
+ "enable-operation-group": { type: "boolean", nullable: true },
234
+ "enable-model-namespace": { type: "boolean", nullable: true },
235
+ "hierarchy-client": { type: "boolean", nullable: true },
236
+ branded: { type: "boolean", nullable: true },
237
+ flavor: { type: "string", nullable: true },
238
+ "module-kind": {
239
+ type: "string",
240
+ nullable: true,
241
+ enum: ["esm", "cjs"],
242
+ default: "esm"
243
+ },
244
+ "compatibility-mode": { type: "boolean", nullable: true },
245
+ "experimental-extensible-enums": { type: "boolean", nullable: true },
246
+ "clear-output-folder": { type: "boolean", nullable: true },
247
+ "ignore-property-name-normalize": { type: "boolean", nullable: true },
248
+ "ignore-enum-member-name-normalize": { type: "boolean", nullable: true },
249
+ "compatibility-query-multi-format": { type: "boolean", nullable: true },
250
+ "typespec-title-map": {
251
+ type: "object",
252
+ additionalProperties: {
253
+ type: "string"
254
+ },
255
+ required: [],
256
+ nullable: true
257
+ }
258
+ },
259
+ required: []
260
+ };
261
+
109
262
  const libDef = {
110
263
  name: "@azure-tools/typespec-ts",
111
264
  diagnostics: {
@@ -229,6 +382,12 @@ const libDef = {
229
382
  default: paramMessage`Please note the decimal type will be converted to number. If you strongly care about precision you can use @encode to encode it as a string for the property - ${"propertyName"}.`
230
383
  }
231
384
  },
385
+ "use-kebab-case-option": {
386
+ severity: "warning",
387
+ messages: {
388
+ default: paramMessage`The option - ${"camelCaseOption"} is deprecated and please use this kebab-case one - ${"kebabCaseOption"}.`
389
+ }
390
+ },
232
391
  "unable-serialized-type": {
233
392
  severity: "warning",
234
393
  messages: {
@@ -288,6 +447,12 @@ const libDef = {
288
447
  messages: {
289
448
  default: paramMessage`Parameter '${"paramName"}' with type '${"paramType"}' is not supported and we would ignore this parameter.`
290
449
  }
450
+ },
451
+ "prefix-adding-in-enum-member": {
452
+ severity: "warning",
453
+ messages: {
454
+ default: paramMessage`Enum member name ${"memberName"} is normalized to ${"normalizedName"} with "_" prefix.`
455
+ }
291
456
  }
292
457
  },
293
458
  emitter: {
@@ -266,7 +266,11 @@ function getDocsWithKnownVersion(
266
266
  }
267
267
  const apiVersionEnum = getApiVersionEnum(dpgContext);
268
268
  if (apiVersionEnum) {
269
- const [_, knownValuesEnum] = buildEnumTypes(dpgContext, apiVersionEnum);
269
+ const [_, knownValuesEnum] = buildEnumTypes(
270
+ dpgContext,
271
+ apiVersionEnum,
272
+ true
273
+ );
270
274
  docs.push(
271
275
  `Known values of {@link ${knownValuesEnum.name}} that the service accepts.`
272
276
  );
@@ -8,7 +8,11 @@ import {
8
8
  StructureKind,
9
9
  TypeAliasDeclarationStructure
10
10
  } from "ts-morph";
11
- import { NameType, normalizeName } from "@azure-tools/rlc-common";
11
+ import {
12
+ fixLeadingNumber,
13
+ NameType,
14
+ normalizeName
15
+ } from "@azure-tools/rlc-common";
12
16
  import {
13
17
  SdkArrayType,
14
18
  SdkBodyModelPropertyType,
@@ -38,10 +42,6 @@ import { SdkContext } from "../utils/interfaces.js";
38
42
  import { addDeclaration } from "../framework/declaration.js";
39
43
  import { buildModelDeserializer } from "./serialization/buildDeserializerFunction.js";
40
44
  import { buildModelSerializer } from "./serialization/buildSerializerFunction.js";
41
- import {
42
- getTypeExpression,
43
- normalizeModelPropertyName
44
- } from "./type-expressions/get-type-expression.js";
45
45
  import path from "path";
46
46
  import { refkey } from "../framework/refkey.js";
47
47
  import { useContext } from "../contextManager.js";
@@ -54,6 +54,10 @@ import { isExtensibleEnum } from "./type-expressions/get-enum-expression.js";
54
54
  import { isDiscriminatedUnion } from "./serialization/serializeUtils.js";
55
55
  import { reportDiagnostic } from "../lib.js";
56
56
  import { NoTarget } from "@typespec/compiler";
57
+ import {
58
+ getTypeExpression,
59
+ normalizeModelPropertyName
60
+ } from "./type-expressions/get-type-expression.js";
57
61
  import { emitQueue } from "../framework/hooks/sdkTypes.js";
58
62
  import { resolveReference } from "../framework/reference.js";
59
63
  import { MultipartHelpers } from "./static-helpers-metadata.js";
@@ -187,7 +191,11 @@ function emitType(context: SdkContext, type: SdkType, sourceFile: SourceFile) {
187
191
  if (!(inputUsage || outputUsage || apiVersionEnumOnly || exceptionUsage)) {
188
192
  return;
189
193
  }
190
- const [enumType, knownValuesEnum] = buildEnumTypes(context, type);
194
+ const [enumType, knownValuesEnum] = buildEnumTypes(
195
+ context,
196
+ type,
197
+ isExtensibleEnum(context, type)
198
+ );
191
199
  if (enumType.name.startsWith("_")) {
192
200
  // skip enum generation for internal enums
193
201
  return;
@@ -355,13 +363,16 @@ function buildNullableType(context: SdkContext, type: SdkNullableType) {
355
363
 
356
364
  export function buildEnumTypes(
357
365
  context: SdkContext,
358
- type: SdkEnumType
366
+ type: SdkEnumType,
367
+ reportMemberNameDiagnostic = false // if reportMemberNameDiagnostic is true, it will report diagnostic for enum member name
359
368
  ): [TypeAliasDeclarationStructure, EnumDeclarationStructure] {
360
369
  const enumDeclaration: EnumDeclarationStructure = {
361
370
  kind: StructureKind.Enum,
362
371
  name: `Known${normalizeModelName(context, type)}`,
363
372
  isExported: true,
364
- members: type.values.map(emitEnumMember)
373
+ members: type.values.map((value) =>
374
+ emitEnumMember(context, value, reportMemberNameDiagnostic)
375
+ )
365
376
  };
366
377
 
367
378
  const enumAsUnion: TypeAliasDeclarationStructure = {
@@ -405,10 +416,31 @@ function getExtensibleEnumDescription(model: SdkEnumType): string | undefined {
405
416
  ].join(" \n");
406
417
  }
407
418
 
408
- function emitEnumMember(member: SdkEnumValueType): EnumMemberStructure {
419
+ function emitEnumMember(
420
+ context: SdkContext,
421
+ member: SdkEnumValueType,
422
+ reportMemberNameDiagnostic = false // if reportMemberNameDiagnostic is true, it will report diagnostic for enum member name
423
+ ): EnumMemberStructure {
424
+ const normalizedMemberName = context.rlcOptions?.ignoreEnumMemberNameNormalize
425
+ ? fixLeadingNumber(member.name, NameType.EnumMemberName) // need to fix the leading number also for enum member
426
+ : normalizeName(member.name, NameType.EnumMemberName, true);
427
+ if (
428
+ reportMemberNameDiagnostic &&
429
+ normalizedMemberName.toLowerCase().startsWith("_") &&
430
+ !member.name.toLowerCase().startsWith("_")
431
+ ) {
432
+ reportDiagnostic(context.program, {
433
+ code: "prefix-adding-in-enum-member",
434
+ format: {
435
+ memberName: member.name,
436
+ normalizedName: normalizedMemberName
437
+ },
438
+ target: NoTarget
439
+ });
440
+ }
409
441
  const memberStructure: EnumMemberStructure = {
410
442
  kind: StructureKind.EnumMember,
411
- name: member.name,
443
+ name: normalizedMemberName,
412
444
  value: member.value
413
445
  };
414
446
 
@@ -192,7 +192,7 @@ function emitMethodSamples(
192
192
  if (isPaging) {
193
193
  exampleFunctionBody.push(`const resArray = new Array();`);
194
194
  exampleFunctionBody.push(
195
- `for await (let item of ${methodCall}) { resArray.push(item); }`
195
+ `for await (const item of ${methodCall}) { resArray.push(item); }`
196
196
  );
197
197
  exampleFunctionBody.push(`console.log(resArray);`);
198
198
  } else if (method.response.type === undefined) {
@@ -263,11 +263,12 @@ export function getClassicalOperation(
263
263
  propertyName?: string;
264
264
  }
265
265
  ) {
266
- return (
266
+ return normalizeName(
267
267
  operationMap.get(declaration) ??
268
- declaration.propertyName ??
269
- declaration.name ??
270
- "FIXME"
268
+ declaration.propertyName ??
269
+ declaration.name ??
270
+ "FIXME",
271
+ NameType.Method
271
272
  );
272
273
  }
273
274
  }
@@ -4,7 +4,11 @@ import {
4
4
  ParameterDeclarationStructure
5
5
  } from "ts-morph";
6
6
  import { NoTarget, Program } from "@typespec/compiler";
7
- import { PagingHelpers, PollingHelpers } from "../static-helpers-metadata.js";
7
+ import {
8
+ PagingHelpers,
9
+ PollingHelpers,
10
+ UrlTemplateHelpers
11
+ } from "../static-helpers-metadata.js";
8
12
  import {
9
13
  getNullableValidType,
10
14
  isSpreadBodyParameter,
@@ -55,6 +59,7 @@ import {
55
59
  SdkModelPropertyType,
56
60
  SdkModelType,
57
61
  SdkPagingServiceMethod,
62
+ SdkPathParameter,
58
63
  SdkServiceParameter,
59
64
  SdkType
60
65
  } from "@azure-tools/typespec-client-generator-core";
@@ -93,6 +98,19 @@ export function getSendPrivateFunction(
93
98
  (p) => p.isApiVersionParam && p.onClient && p.kind === "method"
94
99
  );
95
100
  const statements: string[] = [];
101
+ let pathStr = `"${operationPath}"`;
102
+ const urlTemplateParams = [
103
+ ...getPathParameters(dpgContext, operation),
104
+ ...getQueryParameters(dpgContext, operation)
105
+ ];
106
+ if (urlTemplateParams.length > 0) {
107
+ statements.push(`const path = ${resolveReference(UrlTemplateHelpers.parseTemplate)}("${operation.operation.uriTemplate}", {
108
+ ${urlTemplateParams.join(",\n")}
109
+ },{
110
+ allowReserved: ${optionalParamName}?.requestOptions?.skipUrlEncoding
111
+ });`);
112
+ pathStr = "path";
113
+ }
96
114
  if (hasClientApiVersion && !hasQueryApiVersion) {
97
115
  statements.push(
98
116
  `context.pipeline.removePolicy({ name: "ClientApiVersionPolicy"});`
@@ -100,11 +118,7 @@ export function getSendPrivateFunction(
100
118
  }
101
119
 
102
120
  statements.push(
103
- `return context.path("${operationPath}", ${getPathParameters(
104
- dpgContext,
105
- operation,
106
- optionalParamName
107
- )}).${operationMethod}({...${resolveReference(dependencies.operationOptionsToRequestParameters)}(${optionalParamName}), ${getRequestParameters(
121
+ `return context.path(${pathStr}).${operationMethod}({...${resolveReference(dependencies.operationOptionsToRequestParameters)}(${optionalParamName}), ${getHeaderAndBodyParameters(
108
122
  dpgContext,
109
123
  operation,
110
124
  optionalParamName
@@ -634,7 +648,7 @@ export function getOperationOptionsName(
634
648
  * RLC internally. This will translate High Level parameters into the RLC ones.
635
649
  * Figuring out what goes in headers, body, path and qsp.
636
650
  */
637
- function getRequestParameters(
651
+ function getHeaderAndBodyParameters(
638
652
  dpgContext: SdkContext,
639
653
  operation: ServiceOperation,
640
654
  optionalParamName: string = "options"
@@ -650,16 +664,15 @@ function getRequestParameters(
650
664
  operation.operation.parameters.find(isContentType);
651
665
 
652
666
  const parametersImplementation: Record<
653
- "header" | "query" | "body",
667
+ "header" | "body",
654
668
  { paramMap: string; param: SdkServiceParameter }[]
655
669
  > = {
656
670
  header: [],
657
- query: [],
658
671
  body: []
659
672
  };
660
673
 
661
674
  for (const param of operationParameters) {
662
- if (param.kind === "header" || param.kind === "query") {
675
+ if (param.kind === "header") {
663
676
  // skip tcgc generated contentType and accept non constant type header parameter
664
677
  if (
665
678
  param.isGeneratedName &&
@@ -693,12 +706,6 @@ function getRequestParameters(
693
706
  )
694
707
  .join(",\n")}, ...${optionalParamName}.requestOptions?.headers },`;
695
708
  }
696
-
697
- if (parametersImplementation.query.length) {
698
- paramStr = `${paramStr}\nqueryParameters: {${parametersImplementation.query
699
- .map((i) => i.paramMap)
700
- .join(",\n")}},`;
701
- }
702
709
  if (
703
710
  operation.operation.bodyParam === undefined &&
704
711
  parametersImplementation.body.length
@@ -977,10 +984,10 @@ function getPathParameters(
977
984
  optionalParamName: string = "options"
978
985
  ) {
979
986
  if (!operation.operation.parameters) {
980
- return "";
987
+ return [];
981
988
  }
982
989
 
983
- let pathParams = "";
990
+ const pathParams: string[] = [];
984
991
  for (const param of operation.operation.parameters) {
985
992
  if (param.kind === "path") {
986
993
  // Path parameters cannot be optional
@@ -989,21 +996,55 @@ function getPathParameters(
989
996
  code: "optional-path-param",
990
997
  target: NoTarget,
991
998
  format: {
992
- paramName: param
999
+ paramName: (param as SdkPathParameter).name
993
1000
  }
994
1001
  });
995
1002
  }
996
- pathParams += `${pathParams !== "" ? "," : ""} ${getPathParamExpr(
997
- param,
998
- getDefaultValue(param) as string,
999
- optionalParamName
1000
- )}`;
1003
+ pathParams.push(
1004
+ `${param.serializedName}: ${getPathParamExpr(param, getDefaultValue(param) as string, optionalParamName)}`
1005
+ );
1001
1006
  }
1002
1007
  }
1003
1008
 
1004
1009
  return pathParams;
1005
1010
  }
1006
1011
 
1012
+ /**
1013
+ * Extract the query parameters
1014
+ */
1015
+ function getQueryParameters(
1016
+ dpgContext: SdkContext,
1017
+ operation: ServiceOperation
1018
+ ): string[] {
1019
+ if (!operation.parameters) {
1020
+ return [];
1021
+ }
1022
+ const operationParameters = operation.operation.parameters.filter(
1023
+ (p) => (!p.onClient || p.isApiVersionParam) && !isContentType(p)
1024
+ );
1025
+ const parametersImplementation: Record<
1026
+ "query",
1027
+ { paramMap: string; param: SdkServiceParameter }[]
1028
+ > = {
1029
+ query: []
1030
+ };
1031
+
1032
+ for (const param of operationParameters) {
1033
+ if (param.kind === "query") {
1034
+ parametersImplementation[param.kind].push({
1035
+ paramMap: getParameterMap(dpgContext, param),
1036
+ param
1037
+ });
1038
+ }
1039
+ }
1040
+
1041
+ const paramStr: string[] = parametersImplementation.query.map(
1042
+ (i) => i.paramMap
1043
+ );
1044
+
1045
+ return paramStr;
1046
+ }
1047
+
1007
1048
  function getPathParamExpr(
1008
1049
  param: SdkServiceParameter,
1009
1050
  defaultValue?: string,
@@ -1017,16 +1058,11 @@ function getPathParamExpr(
1017
1058
  : param.optional
1018
1059
  ? `${optionalParamName}["${param.name}"]`
1019
1060
  : param.name;
1020
- const value = defaultValue
1061
+ return defaultValue
1021
1062
  ? typeof defaultValue === "string"
1022
1063
  ? `${paramName} ?? "${defaultValue}"`
1023
1064
  : `${paramName} ?? ${defaultValue}`
1024
1065
  : paramName;
1025
- // TODO allowReserved is not supported in Query and Header parameter yet.
1026
- if (param.kind === "path" && param.allowReserved === true) {
1027
- return `{value: ${value}, allowReserved: true}`;
1028
- }
1029
- return value;
1030
1066
  }
1031
1067
 
1032
1068
  function getNullableCheck(name: string, type: SdkType) {