@azure-tools/typespec-ts 0.40.0 → 0.40.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 (82) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +54 -16
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/lib.d.ts +4 -12
  6. package/dist/src/lib.d.ts.map +1 -1
  7. package/dist/src/lib.js +2 -101
  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 +75 -5
  12. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  13. package/dist/src/modular/buildClassicalOperationGroups.d.ts +1 -1
  14. package/dist/src/modular/buildClassicalOperationGroups.d.ts.map +1 -1
  15. package/dist/src/modular/buildClassicalOperationGroups.js +5 -4
  16. package/dist/src/modular/buildClassicalOperationGroups.js.map +1 -1
  17. package/dist/src/modular/buildClientContext.d.ts +2 -2
  18. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  19. package/dist/src/modular/buildClientContext.js +8 -8
  20. package/dist/src/modular/buildClientContext.js.map +1 -1
  21. package/dist/src/modular/buildOperations.d.ts +1 -1
  22. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  23. package/dist/src/modular/buildOperations.js +3 -2
  24. package/dist/src/modular/buildOperations.js.map +1 -1
  25. package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
  26. package/dist/src/modular/buildProjectFiles.js +16 -7
  27. package/dist/src/modular/buildProjectFiles.js.map +1 -1
  28. package/dist/src/modular/buildRestorePoller.d.ts +1 -1
  29. package/dist/src/modular/buildRestorePoller.d.ts.map +1 -1
  30. package/dist/src/modular/buildRestorePoller.js +3 -2
  31. package/dist/src/modular/buildRestorePoller.js.map +1 -1
  32. package/dist/src/modular/buildRootIndex.d.ts +2 -2
  33. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  34. package/dist/src/modular/buildRootIndex.js +6 -4
  35. package/dist/src/modular/buildRootIndex.js.map +1 -1
  36. package/dist/src/modular/buildSubpathIndex.d.ts +1 -2
  37. package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
  38. package/dist/src/modular/buildSubpathIndex.js +3 -3
  39. package/dist/src/modular/buildSubpathIndex.js.map +1 -1
  40. package/dist/src/modular/emitModelsOptions.d.ts +1 -1
  41. package/dist/src/modular/emitModelsOptions.d.ts.map +1 -1
  42. package/dist/src/modular/emitModelsOptions.js +3 -2
  43. package/dist/src/modular/emitModelsOptions.js.map +1 -1
  44. package/dist/src/modular/emitSamples.d.ts.map +1 -1
  45. package/dist/src/modular/emitSamples.js +3 -2
  46. package/dist/src/modular/emitSamples.js.map +1 -1
  47. package/dist/src/modular/helpers/classicalOperationHelpers.d.ts +1 -1
  48. package/dist/src/modular/helpers/classicalOperationHelpers.d.ts.map +1 -1
  49. package/dist/src/modular/helpers/classicalOperationHelpers.js +2 -2
  50. package/dist/src/modular/helpers/classicalOperationHelpers.js.map +1 -1
  51. package/dist/src/modular/helpers/namingHelpers.js +4 -3
  52. package/dist/src/modular/helpers/namingHelpers.js.map +1 -1
  53. package/dist/src/transform/transfromRLCOptions.d.ts +1 -4
  54. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  55. package/dist/src/transform/transfromRLCOptions.js +58 -262
  56. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  57. package/dist/src/utils/clientUtils.d.ts +2 -1
  58. package/dist/src/utils/clientUtils.d.ts.map +1 -1
  59. package/dist/src/utils/clientUtils.js +38 -5
  60. package/dist/src/utils/clientUtils.js.map +1 -1
  61. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  62. package/dist/src/utils/operationUtil.js +21 -17
  63. package/dist/src/utils/operationUtil.js.map +1 -1
  64. package/dist/tsconfig.tsbuildinfo +1 -1
  65. package/package.json +20 -20
  66. package/src/index.ts +75 -47
  67. package/src/lib.ts +6 -105
  68. package/src/modular/buildClassicalClient.ts +98 -8
  69. package/src/modular/buildClassicalOperationGroups.ts +5 -4
  70. package/src/modular/buildClientContext.ts +8 -10
  71. package/src/modular/buildOperations.ts +3 -5
  72. package/src/modular/buildProjectFiles.ts +19 -8
  73. package/src/modular/buildRestorePoller.ts +3 -2
  74. package/src/modular/buildRootIndex.ts +6 -5
  75. package/src/modular/buildSubpathIndex.ts +3 -5
  76. package/src/modular/emitModelsOptions.ts +3 -2
  77. package/src/modular/emitSamples.ts +3 -2
  78. package/src/modular/helpers/classicalOperationHelpers.ts +2 -2
  79. package/src/modular/helpers/namingHelpers.ts +4 -4
  80. package/src/transform/transfromRLCOptions.ts +60 -305
  81. package/src/utils/clientUtils.ts +44 -8
  82. package/src/utils/operationUtil.ts +23 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-tools/typespec-ts",
3
- "version": "0.40.0",
3
+ "version": "0.40.2",
4
4
  "description": "An experimental TypeSpec emitter for TypeScript RLC",
5
5
  "main": "dist/src/index.js",
6
6
  "type": "module",
@@ -21,11 +21,11 @@
21
21
  "@typespec/http-specs": "0.1.0-alpha.22-dev.0",
22
22
  "@typespec/spector": "0.1.0-alpha.14-dev.1",
23
23
  "@typespec/spec-api": "0.1.0-alpha.7-dev.0",
24
- "@azure-tools/azure-http-specs": "0.1.0-alpha.17-dev.0",
25
- "@azure-tools/typespec-autorest": "0.56.0",
26
- "@azure-tools/typespec-azure-core": "0.56.0",
27
- "@azure-tools/typespec-azure-resource-manager": "0.56.0",
28
- "@azure-tools/typespec-client-generator-core": "0.56.0",
24
+ "@azure-tools/azure-http-specs": "^0.1.0-alpha.17-dev.0",
25
+ "@azure-tools/typespec-autorest": "^0.56.0",
26
+ "@azure-tools/typespec-azure-core": "^0.56.0",
27
+ "@azure-tools/typespec-azure-resource-manager": "^0.56.1",
28
+ "@azure-tools/typespec-client-generator-core": "^0.56.2",
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": "^8.28.0",
42
42
  "@typescript-eslint/parser": "^8.28.0",
43
- "@typespec/compiler": "1.0.0",
44
- "@typespec/http": "1.0.0",
45
- "@typespec/openapi": "1.0.0",
46
- "@typespec/rest": "0.70.0",
47
- "@typespec/ts-http-runtime": "0.1.0",
48
- "@typespec/versioning": "0.70.0",
43
+ "@typespec/compiler": "^1.0.0",
44
+ "@typespec/http": "^1.0.1",
45
+ "@typespec/openapi": "^1.0.0",
46
+ "@typespec/rest": "^0.70.0",
47
+ "@typespec/ts-http-runtime": "^0.1.0",
48
+ "@typespec/versioning": "^0.70.0",
49
49
  "chai": "^4.3.6",
50
50
  "chalk": "^4.0.0",
51
51
  "cross-env": "^7.0.3",
@@ -67,16 +67,16 @@
67
67
  "js-yaml": "^4.1.0"
68
68
  },
69
69
  "peerDependencies": {
70
- "@azure-tools/typespec-azure-core": "0.56.0",
71
- "@azure-tools/typespec-client-generator-core": "0.56.0",
72
- "@typespec/compiler": "1.0.0",
73
- "@typespec/http": "1.0.0",
74
- "@typespec/rest": "0.70.0",
75
- "@typespec/versioning": "0.70.0",
76
- "@typespec/xml": "0.70.0"
70
+ "@azure-tools/typespec-azure-core": "^0.56.0",
71
+ "@azure-tools/typespec-client-generator-core": "^0.56.2",
72
+ "@typespec/compiler": "^1.0.0",
73
+ "@typespec/http": "^1.0.1",
74
+ "@typespec/rest": "^0.70.0",
75
+ "@typespec/versioning": "^0.70.0",
76
+ "@typespec/xml": "^0.70.0"
77
77
  },
78
78
  "dependencies": {
79
- "@azure-tools/rlc-common": "^0.39.0",
79
+ "@azure-tools/rlc-common": "^0.40.2",
80
80
  "fs-extra": "^11.1.0",
81
81
  "lodash": "^4.17.21",
82
82
  "prettier": "^3.3.3",
package/src/index.ts CHANGED
@@ -83,7 +83,7 @@ import { emitLoggerFile } from "./modular/emitLoggerFile.js";
83
83
  import { emitTypes } from "./modular/emitModels.js";
84
84
  import { existsSync } from "fs";
85
85
  import { getModuleExports } from "./modular/buildProjectFiles.js";
86
- import { getRLCClients } from "./utils/clientUtils.js";
86
+ import { getClientHierarchyMap, getRLCClients } from "./utils/clientUtils.js";
87
87
  import { join } from "path";
88
88
  import { loadStaticHelpers } from "./framework/load-static-helpers.js";
89
89
  import { provideBinder } from "./framework/hooks/binder.js";
@@ -166,13 +166,20 @@ export async function $onEmit(context: EmitContext) {
166
166
  console.timeEnd("onEmit: build RLC code models");
167
167
 
168
168
  // 4. Generate sources
169
- if (emitterOptions.isModularLibrary) {
169
+ if (emitterOptions["is-modular-library"]) {
170
170
  await generateModularSources();
171
171
  } else {
172
172
  await generateRLCSources();
173
173
  }
174
174
 
175
175
  // 5. Generate metadata and test files
176
+ function getTypespecTsVersion(context: EmitContext): string | undefined {
177
+ const emitterMetadata = context.program.emitters.find(
178
+ (emitter) => emitter.metadata.name === "@azure-tools/typespec-ts"
179
+ );
180
+ return emitterMetadata?.metadata.version;
181
+ }
182
+
176
183
  await generateMetadataAndTest(dpgContext);
177
184
 
178
185
  async function enrichDpgContext() {
@@ -180,8 +187,8 @@ export async function $onEmit(context: EmitContext) {
180
187
  await calculateGenerationDir();
181
188
  dpgContext.generationPathDetail = generationPathDetail;
182
189
  const options: RLCOptions = transformRLCOptions(emitterOptions, dpgContext);
183
- emitterOptions.isModularLibrary = options.isModularLibrary;
184
- emitterOptions.generateSample = options.generateSample;
190
+ emitterOptions["is-modular-library"] = options.isModularLibrary;
191
+ emitterOptions["generate-sample"] = options.generateSample;
185
192
  // clear output folder if needed
186
193
  if (options.clearOutputFolder) {
187
194
  await fsextra.emptyDir(context.emitterOutputDir);
@@ -283,58 +290,37 @@ export async function $onEmit(context: EmitContext) {
283
290
  console.time("onEmit: emit models");
284
291
  emitTypes(dpgContext, { sourceRoot: modularSourcesRoot });
285
292
  console.timeEnd("onEmit: emit models");
286
- buildSubpathIndexFile(
287
- dpgContext,
288
- modularEmitterOptions,
289
- "models",
290
- undefined,
291
- { recursive: true }
292
- );
293
+ buildSubpathIndexFile(modularEmitterOptions, "models", undefined, {
294
+ recursive: true
295
+ });
293
296
  console.time("onEmit: emit source files");
294
- for (const subClient of dpgContext.sdkPackage.clients) {
295
- await renameClientName(subClient, modularEmitterOptions);
297
+ const clientMap = getClientHierarchyMap(dpgContext);
298
+ for (const subClient of clientMap) {
299
+ await renameClientName(subClient[1], modularEmitterOptions);
296
300
  buildApiOptions(dpgContext, subClient, modularEmitterOptions);
297
301
  buildOperationFiles(dpgContext, subClient, modularEmitterOptions);
298
302
  buildClientContext(dpgContext, subClient, modularEmitterOptions);
299
303
  buildRestorePoller(dpgContext, subClient, modularEmitterOptions);
300
304
  if (dpgContext.rlcOptions?.hierarchyClient) {
301
- buildSubpathIndexFile(
302
- dpgContext,
303
- modularEmitterOptions,
304
- "api",
305
- subClient,
306
- {
307
- exportIndex: false,
308
- recursive: true
309
- }
310
- );
305
+ buildSubpathIndexFile(modularEmitterOptions, "api", subClient, {
306
+ exportIndex: false,
307
+ recursive: true
308
+ });
311
309
  } else {
312
- buildSubpathIndexFile(
313
- dpgContext,
314
- modularEmitterOptions,
315
- "api",
316
- subClient,
317
- {
318
- recursive: true,
319
- exportIndex: true
320
- }
321
- );
310
+ buildSubpathIndexFile(modularEmitterOptions, "api", subClient, {
311
+ recursive: true,
312
+ exportIndex: true
313
+ });
322
314
  }
323
315
 
324
316
  buildClassicalClient(dpgContext, subClient, modularEmitterOptions);
325
317
  buildClassicOperationFiles(dpgContext, subClient, modularEmitterOptions);
326
- buildSubpathIndexFile(
327
- dpgContext,
328
- modularEmitterOptions,
329
- "classic",
330
- subClient,
331
- {
332
- exportIndex: true,
333
- interfaceOnly: true
334
- }
335
- );
318
+ buildSubpathIndexFile(modularEmitterOptions, "classic", subClient, {
319
+ exportIndex: true,
320
+ interfaceOnly: true
321
+ });
336
322
  if (isMultiClients) {
337
- buildSubClientIndexFile(dpgContext, subClient, modularEmitterOptions);
323
+ buildSubClientIndexFile(subClient, modularEmitterOptions);
338
324
  }
339
325
  buildRootIndex(
340
326
  dpgContext,
@@ -345,7 +331,7 @@ export async function $onEmit(context: EmitContext) {
345
331
  }
346
332
  console.timeEnd("onEmit: emit source files");
347
333
  // Enable modular sample generation when explicitly set to true or MPG
348
- if (emitterOptions.generateSample === true) {
334
+ if (emitterOptions["generate-sample"] === true) {
349
335
  console.time("onEmit: emit samples");
350
336
  const samples = emitSamples(dpgContext);
351
337
  console.timeEnd("onEmit: emit samples");
@@ -358,6 +344,9 @@ export async function $onEmit(context: EmitContext) {
358
344
 
359
345
  console.time("onEmit: resolve references");
360
346
  binder.resolveAllReferences(modularSourcesRoot);
347
+ if (program.compilerOptions.noEmit || program.hasError()) {
348
+ return;
349
+ }
361
350
  console.timeEnd("onEmit: resolve references");
362
351
 
363
352
  console.time("onEmit: generate files");
@@ -372,7 +361,29 @@ export async function $onEmit(context: EmitContext) {
372
361
  console.timeEnd("onEmit: generate files");
373
362
  console.timeEnd("onEmit: generate modular sources");
374
363
  }
364
+ interface Metadata {
365
+ apiVersion?: string;
366
+ emitterVersion?: string;
367
+ }
375
368
 
369
+ function buildMetadataJson() {
370
+ const apiVersion = dpgContext.sdkPackage.metadata.apiVersion;
371
+ const emitterVersion = getTypespecTsVersion(context);
372
+ if (apiVersion === undefined && emitterVersion === undefined) {
373
+ return;
374
+ }
375
+ const content: Metadata = {};
376
+ if (apiVersion !== undefined) {
377
+ content.apiVersion = apiVersion;
378
+ }
379
+ if (emitterVersion !== undefined) {
380
+ content.emitterVersion = emitterVersion;
381
+ }
382
+ return {
383
+ path: "metadata.json",
384
+ content: JSON.stringify(content, null, 2)
385
+ };
386
+ }
376
387
  async function generateMetadataAndTest(context: SdkContext) {
377
388
  const project = useContext("outputProject");
378
389
  if (rlcCodeModels.length === 0 || !rlcCodeModels[0]) {
@@ -402,6 +413,14 @@ export async function $onEmit(context: EmitContext) {
402
413
  option.generateTest = true;
403
414
  }
404
415
  }
416
+
417
+ //TODO Need consider multi-client cases
418
+ if (option.isModularLibrary) {
419
+ for (const subClient of dpgContext.sdkPackage.clients) {
420
+ rlcClient.libraryName = subClient.name;
421
+ }
422
+ }
423
+
405
424
  if (shouldGenerateMetadata) {
406
425
  const commonBuilders = [
407
426
  buildRollupConfig,
@@ -486,6 +505,14 @@ export async function $onEmit(context: EmitContext) {
486
505
  dpgContext.generationPathDetail?.metadataDir
487
506
  );
488
507
  }
508
+ if (isAzureFlavor) {
509
+ await emitContentByBuilder(
510
+ program,
511
+ buildMetadataJson,
512
+ rlcClient,
513
+ dpgContext.generationPathDetail?.metadataDir
514
+ );
515
+ }
489
516
 
490
517
  // Generate test relevant files
491
518
  if (option.generateTest && isAzureFlavor) {
@@ -502,8 +529,9 @@ export async function $onEmit(context: EmitContext) {
502
529
  context: SdkContext,
503
530
  options: ModularEmitterOptions
504
531
  ) {
505
- return context.sdkPackage.clients
506
- .map((subClient) => getClientContextPath(context, subClient, options))
532
+ const clientMap = getClientHierarchyMap(context);
533
+ return Array.from(clientMap)
534
+ .map((subClient) => getClientContextPath(subClient, options))
507
535
  .map((path) => path.substring(path.indexOf("src")));
508
536
  }
509
537
  console.timeEnd("onEmit");
package/src/lib.ts CHANGED
@@ -5,8 +5,7 @@ import {
5
5
  PackageDetails,
6
6
  DependencyInfo,
7
7
  ServiceInfo,
8
- PackageFlavor,
9
- RLCOptions
8
+ PackageFlavor
10
9
  } from "@azure-tools/rlc-common";
11
10
  import {
12
11
  createTypeSpecLibrary,
@@ -15,7 +14,7 @@ import {
15
14
  } from "@typespec/compiler";
16
15
  import { Options } from "prettier";
17
16
 
18
- export interface EmitterOptions extends RLCOptions {
17
+ export interface EmitterOptions {
19
18
  "include-shortcuts"?: boolean;
20
19
  "multi-client"?: boolean;
21
20
  batch?: any[];
@@ -69,107 +68,14 @@ export interface EmitterOptions extends RLCOptions {
69
68
  "typespec-title-map"?: Record<string, string>;
70
69
  "ignore-enum-member-name-normalize"?: boolean;
71
70
  "default-value-object"?: boolean;
71
+ //TODO should remove this after finish the release tool test
72
+ "should-use-pnpm-dep"?: boolean;
72
73
  }
73
74
 
74
- const _RLCOptionsSchema: JSONSchemaType<RLCOptions> = {
75
- type: "object",
76
- additionalProperties: true,
77
- properties: {
78
- includeShortcuts: { type: "boolean", nullable: true },
79
- multiClient: { type: "boolean", nullable: true },
80
- batch: {
81
- type: "array",
82
- nullable: true,
83
- items: {
84
- type: "string"
85
- }
86
- },
87
- packageDetails: {
88
- type: "object",
89
- additionalProperties: true,
90
- properties: {
91
- name: { type: "string", nullable: false },
92
- scopeName: { type: "string", nullable: true },
93
- nameWithoutScope: { type: "string", nullable: true },
94
- description: { type: "string", nullable: true },
95
- version: { type: "string", nullable: true }
96
- },
97
- required: ["name"],
98
- nullable: true
99
- },
100
- addCredentials: { type: "boolean", nullable: true },
101
- credentialScopes: {
102
- type: "array",
103
- nullable: true,
104
- items: { type: "string" }
105
- },
106
- credentialKeyHeaderName: { type: "string", nullable: true },
107
- customHttpAuthHeaderName: { type: "string", nullable: true },
108
- customHttpAuthSharedKeyPrefix: { type: "string", nullable: true },
109
- generateMetadata: { type: "boolean", nullable: true },
110
- generateTest: { type: "boolean", nullable: true },
111
- generateSample: { type: "boolean", nullable: true },
112
- azureSdkForJs: { type: "boolean", nullable: true },
113
- azureOutputDirectory: { type: "string", nullable: true },
114
- isTypeSpecTest: { type: "boolean", nullable: true },
115
- title: { type: "string", nullable: true },
116
- dependencyInfo: {
117
- type: "object",
118
- additionalProperties: true,
119
- properties: {
120
- link: { type: "string", nullable: false },
121
- description: { type: "string", nullable: false }
122
- },
123
- required: [],
124
- nullable: true
125
- },
126
- productDocLink: { type: "string", nullable: true },
127
- serviceInfo: {
128
- type: "object",
129
- additionalProperties: true,
130
- properties: {
131
- title: { type: "string", nullable: true },
132
- description: { type: "string", nullable: true }
133
- },
134
- nullable: true
135
- },
136
- azureArm: { type: "boolean", nullable: true },
137
- sourceFrom: { type: "string", nullable: true },
138
- isModularLibrary: { type: "boolean", nullable: true, default: false },
139
- enableOperationGroup: { type: "boolean", nullable: true },
140
- enableModelNamespace: { type: "boolean", nullable: true },
141
- hierarchyClient: { type: "boolean", nullable: true },
142
- branded: { type: "boolean", nullable: true },
143
- flavor: { type: "string", nullable: true },
144
- moduleKind: {
145
- type: "string",
146
- nullable: true,
147
- enum: ["esm", "cjs"],
148
- default: "esm"
149
- },
150
- compatibilityMode: { type: "boolean", nullable: true },
151
- experimentalExtensibleEnums: { type: "boolean", nullable: true },
152
- clearOutputFolder: { type: "boolean", nullable: true },
153
- ignorePropertyNameNormalize: { type: "boolean", nullable: true },
154
- ignoreEnumMemberNameNormalize: { type: "boolean", nullable: true },
155
- compatibilityQueryMultiFormat: { type: "boolean", nullable: true },
156
- typespecTitleMap: {
157
- type: "object",
158
- additionalProperties: {
159
- type: "string"
160
- },
161
- required: [],
162
- nullable: true
163
- }
164
- },
165
- required: []
166
- };
167
-
168
75
  export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
169
76
  type: "object",
170
77
  additionalProperties: true,
171
78
  properties: {
172
- ..._RLCOptionsSchema.properties,
173
79
  "include-shortcuts": { type: "boolean", nullable: true },
174
80
  "multi-client": { type: "boolean", nullable: true },
175
81
  batch: {
@@ -256,7 +162,8 @@ export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
256
162
  },
257
163
  required: [],
258
164
  nullable: true
259
- }
165
+ },
166
+ "should-use-pnpm-dep": { type: "boolean", nullable: true }
260
167
  },
261
168
  required: []
262
169
  };
@@ -384,12 +291,6 @@ const libDef = {
384
291
  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"}.`
385
292
  }
386
293
  },
387
- "use-kebab-case-option": {
388
- severity: "warning",
389
- messages: {
390
- default: paramMessage`The option - ${"camelCaseOption"} is deprecated and please use this kebab-case one - ${"kebabCaseOption"}.`
391
- }
392
- },
393
294
  "unable-serialized-type": {
394
295
  severity: "warning",
395
296
  messages: {
@@ -26,6 +26,7 @@ import {
26
26
  import { resolveReference } from "../framework/reference.js";
27
27
  import { useDependencies } from "../framework/hooks/useDependencies.js";
28
28
  import {
29
+ InitializedByFlags,
29
30
  SdkClientType,
30
31
  SdkServiceMethod,
31
32
  SdkServiceOperation
@@ -36,10 +37,11 @@ import { refkey } from "../framework/refkey.js";
36
37
 
37
38
  export function buildClassicalClient(
38
39
  dpgContext: SdkContext,
39
- client: SdkClientType<SdkServiceOperation>,
40
+ clientMap: [string[], SdkClientType<SdkServiceOperation>],
40
41
  emitterOptions: ModularEmitterOptions
41
42
  ) {
42
43
  const project = useContext("outputProject");
44
+ const [_hierarchy, client] = clientMap;
43
45
  const dependencies = useDependencies();
44
46
  const modularClientName = getClientName(client);
45
47
  const classicalClientName = `${getClassicalClientName(client)}`;
@@ -51,10 +53,7 @@ export function buildClassicalClient(
51
53
  requiredOnly: true
52
54
  });
53
55
  const srcPath = emitterOptions.modularOptions.sourceRoot;
54
- const { subfolder, rlcClientName } = getModularClientOptions(
55
- dpgContext,
56
- client
57
- );
56
+ const { subfolder, rlcClientName } = getModularClientOptions(clientMap);
58
57
 
59
58
  const clientFile = project.createSourceFile(
60
59
  `${srcPath}/${subfolder && subfolder !== "" ? subfolder + "/" : ""}${normalizeName(
@@ -99,6 +98,25 @@ export function buildClassicalClient(
99
98
  docs: ["The pipeline used by this client to make requests"]
100
99
  });
101
100
 
101
+ const hasChildClient =
102
+ client.children &&
103
+ client.children.some((childClient) => {
104
+ return (
105
+ childClient.clientInitialization.initializedBy &
106
+ InitializedByFlags.Parent
107
+ );
108
+ });
109
+ if (hasChildClient) {
110
+ clientClass.addProperty({
111
+ name: "_clientParams",
112
+ type: `{${classicalParams.map((p) => {
113
+ return `${p.name}: ${p.type}`;
114
+ })}}`,
115
+ scope: Scope.Private,
116
+ docs: ["The parent client parameters that are used in the constructors."]
117
+ });
118
+ }
119
+
102
120
  // TODO: We may need to generate constructor overloads at some point. Here we'd do that.
103
121
  const constructor = clientClass.addConstructor({
104
122
  docs: getDocsFromDescription(client.doc),
@@ -124,7 +142,37 @@ export function buildClassicalClient(
124
142
  ]);
125
143
  constructor.addStatements(`this.pipeline = this._client.pipeline;`);
126
144
 
127
- buildClientOperationGroups(client, dpgContext, clientClass);
145
+ if (hasChildClient && client.children) {
146
+ constructor.addStatements(
147
+ `this._clientParams = {${classicalParams.map((p) => p.name).join(",")}};`
148
+ );
149
+ for (const childClient of client.children) {
150
+ const subfolder = normalizeName(
151
+ childClient.name.replace("Client", ""),
152
+ NameType.File
153
+ );
154
+ clientFile.addImportDeclaration({
155
+ moduleSpecifier: `./${subfolder}/${normalizeName(childClient.name, NameType.File)}.js`,
156
+ namedImports: [
157
+ `${getClassicalClientName(childClient)}`,
158
+ `${getClassicalClientName(childClient)}OptionalParams`
159
+ ]
160
+ });
161
+ }
162
+ }
163
+ buildClientOperationGroups(clientMap, dpgContext, clientClass);
164
+ if (client.children) {
165
+ client.children
166
+ .filter((childClient) => {
167
+ return (
168
+ childClient.clientInitialization.initializedBy &
169
+ InitializedByFlags.Parent
170
+ );
171
+ })
172
+ .forEach((childClient) => {
173
+ addChildClient(dpgContext, clientClass, client, childClient);
174
+ });
175
+ }
128
176
  importAllApis(clientFile, srcPath, subfolder ?? "");
129
177
  clientFile.fixUnusedIdentifiers();
130
178
  return clientFile;
@@ -176,12 +224,13 @@ function generateMethod(
176
224
  return result;
177
225
  }
178
226
  function buildClientOperationGroups(
179
- client: SdkClientType<SdkServiceOperation>,
227
+ clientMap: [string[], SdkClientType<SdkServiceOperation>],
180
228
  dpgContext: SdkContext,
181
229
  clientClass: ClassDeclaration
182
230
  ) {
183
231
  let clientType = "Client";
184
- const { subfolder } = getModularClientOptions(dpgContext, client);
232
+ const [_hierarchy, client] = clientMap;
233
+ const { subfolder } = getModularClientOptions(clientMap);
185
234
  if (subfolder && subfolder !== "") {
186
235
  clientType = `Client.${clientClass.getName()}`;
187
236
  }
@@ -229,3 +278,44 @@ function buildClientOperationGroups(
229
278
  }
230
279
  }
231
280
  }
281
+
282
+ function addChildClient(
283
+ context: SdkContext,
284
+ clientClass: ClassDeclaration,
285
+ parentClient: SdkClientType<SdkServiceOperation>,
286
+ client: SdkClientType<SdkServiceOperation>
287
+ ) {
288
+ const parentParams = getClientParametersDeclaration(parentClient, context, {
289
+ requiredOnly: true
290
+ });
291
+ const clientParams = getClientParametersDeclaration(client, context, {
292
+ requiredOnly: true
293
+ });
294
+ const diffParams = clientParams.filter((p) => {
295
+ return !parentParams.some(
296
+ (pp) => pp.name === p.name && pp.name !== "options"
297
+ );
298
+ });
299
+ const name = getClassicalClientName(client);
300
+ const getChildClientFunction = clientClass.addMethod({
301
+ docs: getDocsFromDescription(client.doc),
302
+ name: `get${name}`,
303
+ returnType: `${getClassicalClientName(client)}`,
304
+ parameters: diffParams
305
+ });
306
+ getChildClientFunction.addStatements(
307
+ `return new ${getClassicalClientName(client)}(
308
+ ${parentParams
309
+ .filter((p) => !p.name.includes("options"))
310
+ .map((p) => `this._clientParams.${p.name}`)
311
+ .join(",")},
312
+ ${diffParams
313
+ .filter((p) => p.name !== "options")
314
+ .map((p) => `${p.name}`)
315
+ .join(
316
+ ","
317
+ )}${diffParams.filter((p) => p.name !== "options").length > 0 ? "," : ""}
318
+ { ...this._clientParams.options, ...options }
319
+ )`
320
+ );
321
+ }
@@ -14,12 +14,13 @@ import { useContext } from "../contextManager.js";
14
14
 
15
15
  export function buildClassicOperationFiles(
16
16
  dpgContext: SdkContext,
17
- client: SdkClientType<SdkServiceOperation>,
17
+ clientMap: [string[], SdkClientType<SdkServiceOperation>],
18
18
  emitterOptions: ModularEmitterOptions
19
19
  ) {
20
20
  // const sdkPackage = dpgContext.sdkPackage;
21
21
  const project = useContext("outputProject");
22
- const { subfolder } = getModularClientOptions(dpgContext, client);
22
+ const [_hierarchy, client] = clientMap;
23
+ const { subfolder } = getModularClientOptions(clientMap);
23
24
  const classicOperationFiles: Map<string, SourceFile> = new Map<
24
25
  string,
25
26
  SourceFile
@@ -48,7 +49,7 @@ export function buildClassicOperationFiles(
48
49
  subfolder && subfolder !== "" ? subfolder + "/" : ""
49
50
  }classic/${classicOperationFileName}.ts`
50
51
  );
51
- getClassicalOperation(dpgContext, client, classicFile, [
52
+ getClassicalOperation(dpgContext, clientMap, classicFile, [
52
53
  prefixes,
53
54
  operations
54
55
  ]);
@@ -80,7 +81,7 @@ export function buildClassicOperationFiles(
80
81
  );
81
82
  getClassicalOperation(
82
83
  dpgContext,
83
- client,
84
+ clientMap,
84
85
  classicFile,
85
86
  [prefixes, operations],
86
87
  layer
@@ -38,11 +38,11 @@ import { refkey } from "../framework/refkey.js";
38
38
  * This function gets the path of the file containing the modular client context
39
39
  */
40
40
  export function getClientContextPath(
41
- context: SdkContext,
42
- client: SdkClientType<SdkServiceOperation>,
41
+ clientMap: [string[], SdkClientType<SdkServiceOperation>],
43
42
  emitterOptions: ModularEmitterOptions
44
43
  ): string {
45
- const { subfolder } = getModularClientOptions(context, client);
44
+ const [_, client] = clientMap;
45
+ const { subfolder } = getModularClientOptions(clientMap);
46
46
  const name = getClientName(client);
47
47
  const srcPath = emitterOptions.modularOptions.sourceRoot;
48
48
  const contentPath = `${srcPath}/${
@@ -56,20 +56,21 @@ export function getClientContextPath(
56
56
  */
57
57
  export function buildClientContext(
58
58
  dpgContext: SdkContext,
59
- client: SdkClientType<SdkServiceOperation>,
59
+ clientMap: [string[], SdkClientType<SdkServiceOperation>],
60
60
  emitterOptions: ModularEmitterOptions
61
61
  ): SourceFile {
62
62
  const project = useContext("outputProject");
63
63
  const dependencies = useDependencies();
64
+ const [hierarchy, client] = clientMap;
64
65
  const name = getClientName(client);
65
- const { rlcClientName } = getModularClientOptions(dpgContext, client);
66
+ const { rlcClientName } = getModularClientOptions(clientMap);
66
67
  const requiredParams = getClientParametersDeclaration(client, dpgContext, {
67
68
  onClientOnly: false,
68
69
  requiredOnly: true,
69
70
  apiVersionAsRequired: true
70
71
  });
71
72
  const clientContextFile = project.createSourceFile(
72
- getClientContextPath(dpgContext, client, emitterOptions)
73
+ getClientContextPath(clientMap, emitterOptions)
73
74
  );
74
75
 
75
76
  clientContextFile.addInterface({
@@ -125,10 +126,7 @@ export function buildClientContext(
125
126
  // (for now) now logger for unbranded pkgs
126
127
  if (isAzurePackage(emitterOptions)) {
127
128
  clientContextFile.addImportDeclaration({
128
- moduleSpecifier:
129
- dpgContext.sdkPackage.clients.length > 1
130
- ? "../../logger.js"
131
- : "../logger.js",
129
+ moduleSpecifier: "../".repeat(hierarchy.length + 1) + "logger.js",
132
130
  namedImports: ["logger"]
133
131
  });
134
132
  }