@azure-tools/typespec-ts 0.14.0 → 0.15.0-alpha.20230822.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/src/index.d.ts +1 -5
  3. package/dist/src/index.d.ts.map +1 -1
  4. package/dist/src/index.js +148 -78
  5. package/dist/src/index.js.map +1 -1
  6. package/dist/src/lib.d.ts.map +1 -1
  7. package/dist/src/lib.js +4 -2
  8. package/dist/src/lib.js.map +1 -1
  9. package/dist/src/modular/buildClassicalClient.d.ts +1 -1
  10. package/dist/src/modular/buildClassicalClient.d.ts.map +1 -1
  11. package/dist/src/modular/buildClassicalClient.js +27 -15
  12. package/dist/src/modular/buildClassicalClient.js.map +1 -1
  13. package/dist/src/modular/buildClientContext.d.ts +1 -1
  14. package/dist/src/modular/buildClientContext.d.ts.map +1 -1
  15. package/dist/src/modular/buildClientContext.js +16 -7
  16. package/dist/src/modular/buildClientContext.js.map +1 -1
  17. package/dist/src/modular/buildCodeModel.d.ts.map +1 -1
  18. package/dist/src/modular/buildCodeModel.js +59 -12
  19. package/dist/src/modular/buildCodeModel.js.map +1 -1
  20. package/dist/src/modular/buildOperations.d.ts +2 -1
  21. package/dist/src/modular/buildOperations.d.ts.map +1 -1
  22. package/dist/src/modular/buildOperations.js +25 -29
  23. package/dist/src/modular/buildOperations.js.map +1 -1
  24. package/dist/src/modular/buildProjectFiles.d.ts +2 -2
  25. package/dist/src/modular/buildProjectFiles.d.ts.map +1 -1
  26. package/dist/src/modular/buildProjectFiles.js +284 -145
  27. package/dist/src/modular/buildProjectFiles.js.map +1 -1
  28. package/dist/src/modular/buildRootIndex.d.ts.map +1 -1
  29. package/dist/src/modular/buildRootIndex.js +5 -5
  30. package/dist/src/modular/buildRootIndex.js.map +1 -1
  31. package/dist/src/modular/buildSubpathIndex.d.ts.map +1 -1
  32. package/dist/src/modular/buildSubpathIndex.js +9 -2
  33. package/dist/src/modular/buildSubpathIndex.js.map +1 -1
  34. package/dist/src/modular/emitModels.d.ts +3 -2
  35. package/dist/src/modular/emitModels.d.ts.map +1 -1
  36. package/dist/src/modular/emitModels.js +40 -7
  37. package/dist/src/modular/emitModels.js.map +1 -1
  38. package/dist/src/modular/helpers/clientHelpers.d.ts.map +1 -1
  39. package/dist/src/modular/helpers/clientHelpers.js +5 -3
  40. package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
  41. package/dist/src/modular/helpers/docsHelpers.d.ts +3 -0
  42. package/dist/src/modular/helpers/docsHelpers.d.ts.map +1 -0
  43. package/dist/src/modular/helpers/docsHelpers.js +10 -0
  44. package/dist/src/modular/helpers/docsHelpers.js.map +1 -0
  45. package/dist/src/modular/helpers/operationHelpers.d.ts +11 -4
  46. package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
  47. package/dist/src/modular/helpers/operationHelpers.js +197 -56
  48. package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
  49. package/dist/src/modular/helpers/typeHelpers.d.ts.map +1 -1
  50. package/dist/src/modular/helpers/typeHelpers.js +6 -0
  51. package/dist/src/modular/helpers/typeHelpers.js.map +1 -1
  52. package/dist/src/modular/modularCodeModel.d.ts +2 -0
  53. package/dist/src/modular/modularCodeModel.d.ts.map +1 -1
  54. package/dist/src/transform/transform.d.ts +5 -8
  55. package/dist/src/transform/transform.d.ts.map +1 -1
  56. package/dist/src/transform/transform.js +23 -13
  57. package/dist/src/transform/transform.js.map +1 -1
  58. package/dist/src/transform/transformApiVersionInfo.d.ts +2 -1
  59. package/dist/src/transform/transformApiVersionInfo.d.ts.map +1 -1
  60. package/dist/src/transform/transformApiVersionInfo.js.map +1 -1
  61. package/dist/src/transform/transformHelperFunctionDetails.d.ts +2 -1
  62. package/dist/src/transform/transformHelperFunctionDetails.d.ts.map +1 -1
  63. package/dist/src/transform/transformHelperFunctionDetails.js +4 -10
  64. package/dist/src/transform/transformHelperFunctionDetails.js.map +1 -1
  65. package/dist/src/transform/transformParameters.d.ts +2 -12
  66. package/dist/src/transform/transformParameters.d.ts.map +1 -1
  67. package/dist/src/transform/transformParameters.js +6 -47
  68. package/dist/src/transform/transformParameters.js.map +1 -1
  69. package/dist/src/transform/transformPaths.d.ts +2 -2
  70. package/dist/src/transform/transformPaths.d.ts.map +1 -1
  71. package/dist/src/transform/transformPaths.js.map +1 -1
  72. package/dist/src/transform/transformResponses.d.ts +2 -2
  73. package/dist/src/transform/transformResponses.d.ts.map +1 -1
  74. package/dist/src/transform/transformResponses.js +5 -1
  75. package/dist/src/transform/transformResponses.js.map +1 -1
  76. package/dist/src/transform/transformSchemas.d.ts +2 -2
  77. package/dist/src/transform/transformSchemas.d.ts.map +1 -1
  78. package/dist/src/transform/transformSchemas.js.map +1 -1
  79. package/dist/src/transform/transformTelemetryInfo.d.ts +4 -0
  80. package/dist/src/transform/transformTelemetryInfo.d.ts.map +1 -0
  81. package/dist/src/transform/transformTelemetryInfo.js +42 -0
  82. package/dist/src/transform/transformTelemetryInfo.js.map +1 -0
  83. package/dist/src/transform/transfromRLCOptions.d.ts +4 -2
  84. package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
  85. package/dist/src/transform/transfromRLCOptions.js +72 -19
  86. package/dist/src/transform/transfromRLCOptions.js.map +1 -1
  87. package/dist/src/utils/clientUtils.d.ts +2 -1
  88. package/dist/src/utils/clientUtils.d.ts.map +1 -1
  89. package/dist/src/utils/clientUtils.js.map +1 -1
  90. package/dist/src/utils/interfaces.d.ts +13 -0
  91. package/dist/src/utils/interfaces.d.ts.map +1 -0
  92. package/dist/src/utils/interfaces.js +2 -0
  93. package/dist/src/utils/interfaces.js.map +1 -0
  94. package/dist/src/utils/modelUtils.d.ts +1 -1
  95. package/dist/src/utils/modelUtils.d.ts.map +1 -1
  96. package/dist/src/utils/modelUtils.js +25 -20
  97. package/dist/src/utils/modelUtils.js.map +1 -1
  98. package/dist/src/utils/operationUtil.d.ts +15 -4
  99. package/dist/src/utils/operationUtil.d.ts.map +1 -1
  100. package/dist/src/utils/operationUtil.js +65 -1
  101. package/dist/src/utils/operationUtil.js.map +1 -1
  102. package/dist/tsconfig.tsbuildinfo +1 -1
  103. package/package.json +28 -18
  104. package/src/index.ts +231 -129
  105. package/src/lib.ts +4 -2
  106. package/src/modular/buildClassicalClient.ts +33 -16
  107. package/src/modular/buildClientContext.ts +18 -8
  108. package/src/modular/buildCodeModel.ts +71 -13
  109. package/src/modular/buildOperations.ts +31 -36
  110. package/src/modular/buildProjectFiles.ts +329 -162
  111. package/src/modular/buildRootIndex.ts +5 -7
  112. package/src/modular/buildSubpathIndex.ts +9 -2
  113. package/src/modular/emitModels.ts +55 -9
  114. package/src/modular/helpers/clientHelpers.ts +5 -3
  115. package/src/modular/helpers/docsHelpers.ts +10 -0
  116. package/src/modular/helpers/operationHelpers.ts +328 -75
  117. package/src/modular/helpers/typeHelpers.ts +6 -0
  118. package/src/modular/modularCodeModel.ts +2 -0
  119. package/src/transform/transform.ts +24 -31
  120. package/src/transform/transformApiVersionInfo.ts +1 -1
  121. package/src/transform/transformHelperFunctionDetails.ts +12 -11
  122. package/src/transform/transformParameters.ts +20 -63
  123. package/src/transform/transformPaths.ts +5 -5
  124. package/src/transform/transformResponses.ts +10 -6
  125. package/src/transform/transformSchemas.ts +2 -2
  126. package/src/transform/transformTelemetryInfo.ts +72 -0
  127. package/src/transform/transfromRLCOptions.ts +100 -23
  128. package/src/utils/clientUtils.ts +2 -4
  129. package/src/utils/interfaces.ts +14 -0
  130. package/src/utils/modelUtils.ts +18 -11
  131. package/src/utils/operationUtil.ts +92 -6
  132. package/dist/src/modular/helpers/fixmeHelpers.d.ts +0 -2
  133. package/dist/src/modular/helpers/fixmeHelpers.d.ts.map +0 -1
  134. package/dist/src/modular/helpers/fixmeHelpers.js +0 -4
  135. package/dist/src/modular/helpers/fixmeHelpers.js.map +0 -1
  136. package/dist/src/modular/helpers/parameterHelpers.d.ts +0 -3
  137. package/dist/src/modular/helpers/parameterHelpers.d.ts.map +0 -1
  138. package/dist/src/modular/helpers/parameterHelpers.js +0 -16
  139. package/dist/src/modular/helpers/parameterHelpers.js.map +0 -1
  140. package/src/modular/helpers/fixmeHelpers.ts +0 -3
  141. package/src/modular/helpers/parameterHelpers.ts +0 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azure-tools/typespec-ts",
3
- "version": "0.14.0",
3
+ "version": "0.15.0-alpha.20230822.1",
4
4
  "description": "An experimental CADL emitter for TypeScript RLC",
5
5
  "main": "dist/src/index.js",
6
6
  "type": "module",
@@ -22,30 +22,31 @@
22
22
  "ts-node": "^10.9.1",
23
23
  "typescript": "~5.0.0",
24
24
  "prettier": "~2.7.1",
25
- "@azure-tools/cadl-ranch-specs": "^0.17.1",
26
- "@azure-tools/cadl-ranch-expect": "^0.5.0",
27
- "@azure-tools/cadl-ranch": "^0.6.0",
25
+ "@azure-tools/cadl-ranch-specs": "^0.18.0",
26
+ "@azure-tools/cadl-ranch-expect": "^0.6.0",
27
+ "@azure-tools/cadl-ranch": "^0.7.0",
28
28
  "chalk": "^4.0.0",
29
29
  "@azure-rest/core-client": "^1.1.4",
30
30
  "@azure/core-auth": "^1.3.2",
31
31
  "cross-env": "^7.0.3",
32
32
  "@azure/core-paging": "^1.5.0",
33
33
  "@azure/core-lro": "^2.5.4",
34
- "@azure/core-rest-pipeline": "^1.9.2",
35
- "@azure/logger": "^1.0.4"
34
+ "@azure/core-rest-pipeline": "^1.12.0",
35
+ "@azure/logger": "^1.0.4",
36
+ "@azure/core-util": "^1.4.0"
36
37
  },
37
38
  "peerDependencies": {
38
- "@azure-tools/typespec-azure-core": ">=0.32.0 <1.0.0",
39
- "@azure-tools/typespec-client-generator-core": ">=0.32.0 <1.0.0",
40
- "@typespec/compiler": ">=0.46.0 <1.0.0",
41
- "@typespec/http": ">=0.46.0 <1.0.0",
42
- "@typespec/rest": ">=0.46.0 <1.0.0",
43
- "@typespec/versioning": ">=0.46.0 <1.0.0"
39
+ "@azure-tools/typespec-azure-core": ">=0.33.0 <1.0.0",
40
+ "@azure-tools/typespec-client-generator-core": ">=0.33.0 <1.0.0",
41
+ "@typespec/compiler": ">=0.47.0 <1.0.0",
42
+ "@typespec/http": ">=0.47.0 <1.0.0",
43
+ "@typespec/rest": ">=0.47.0 <1.0.0",
44
+ "@typespec/versioning": ">=0.47.0 <1.0.0"
44
45
  },
45
46
  "dependencies": {
46
47
  "prettier": "^2.6.1",
47
48
  "tslib": "^2.3.1",
48
- "@azure-tools/rlc-common": "^0.14.0",
49
+ "@azure-tools/rlc-common": "^0.15.0",
49
50
  "ts-morph": "^15.1.0",
50
51
  "fs-extra": "^11.1.0"
51
52
  },
@@ -76,12 +77,21 @@
76
77
  "check-format": "npm run prettier -- --check",
77
78
  "prettier": "prettier --config ./.prettierrc src/**/*.ts",
78
79
  "check:tree": "ts-node ./test/commands/check-clean-tree.ts",
79
- "integration-test-ci": "npm run start-test-server & npm run copy:typespec && npm run generate-and-run",
80
- "start-test-server": "mkdirp -p coverage && npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./coverage/cadl-ranch-coverage-typescript-rlc.json",
80
+ "integration-test-ci": "npm run integration-test-ci:rlc && npm run integration-test-ci:modular",
81
+ "integration-test-ci:rlc": "npm run start-test-server:rlc & npm run copy:typespec && npm run generate-and-run:rlc",
82
+ "integration-test-ci:modular": "npm run start-test-server:modular & npm run copy:typespec && npm run generate-and-run:modular",
83
+ "start-test-server": "mkdirp -p coverage && npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./coverage/cadl-ranch-coverage-typescript.json",
84
+ "start-test-server:rlc": "mkdirp -p coverage && npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./coverage/cadl-ranch-coverage-typescript-rlc.json",
85
+ "start-test-server:modular": "mkdirp -p coverage && npx cadl-ranch serve ./node_modules/@azure-tools/cadl-ranch-specs/http --coverageFile ./coverage/cadl-ranch-coverage-typescript-modular.json",
81
86
  "copy:typespec": "rm -rf temp && mkdirp -p temp && cp -r ./node_modules/@azure-tools/cadl-ranch-specs/http ./temp && cp -r ./test/integration/typespec/* ./temp/http",
82
- "generate-and-run": "npm run generate-cadl-only && npm run integration-test:alone && npm run stop-test-server",
83
- "generate-cadl-only": "ts-node ./test/commands/gen-cadl-ranch.ts",
84
- "integration-test:alone": "cross-env TS_NODE_PROJECT=tsconfig.test.json mocha -r ts-node/register --experimental-specifier-resolution=node --timeout 4000 ./test/integration/*.spec.ts",
87
+ "generate-and-run:rlc": "npm run generate-cadl-only:rlc && npm run integration-test:alone:rlc && npm run stop-test-server",
88
+ "generate-and-run:modular": "npm run generate-cadl-only:modular && npm run integration-test:alone:modular && npm run stop-test-server",
89
+ "generate-cadl-only": "npm run generate-cadl-only:rlc && npm run generate-cadl-only:modular",
90
+ "generate-cadl-only:rlc": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=rlc",
91
+ "generate-cadl-only:modular": "ts-node ./test/commands/gen-cadl-ranch.ts --tag=modular",
92
+ "integration-test:alone": "npm run integration-test:alone:rlc && npm run integration-test:alone:modular",
93
+ "integration-test:alone:rlc": "cross-env TS_NODE_PROJECT=tsconfig.test.json mocha -r ts-node/register --experimental-specifier-resolution=node --timeout 4000 ./test/integration/*.spec.ts",
94
+ "integration-test:alone:modular": "cross-env TS_NODE_PROJECT=tsconfig.test.json mocha -r ts-node/register --experimental-specifier-resolution=node --timeout 4000 ./test/modularIntegration/*.spec.ts",
85
95
  "stop-test-server": "npx cadl-ranch server stop",
86
96
  "unit-test": "cross-env TS_NODE_PROJECT=tsconfig.json mocha -r ts-node/register --experimental-specifier-resolution=node --experimental-modules=true --timeout 4000 './test/unit/**/*.spec.ts'"
87
97
  }
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  import { Program, EmitContext } from "@typespec/compiler";
5
5
  import * as fsextra from "fs-extra";
6
+ import { existsSync } from "fs";
6
7
  import {
7
8
  buildClientDefinitions,
8
9
  buildResponseTypes,
@@ -34,11 +35,7 @@ import {
34
35
  } from "@azure-tools/rlc-common";
35
36
  import { transformRLCModel } from "./transform/transform.js";
36
37
  import { emitContentByBuilder, emitModels } from "./utils/emitUtil.js";
37
- import {
38
- SdkContext,
39
- createSdkContext
40
- } from "@azure-tools/typespec-client-generator-core";
41
- import * as path from "path";
38
+ import { createSdkContext } from "@azure-tools/typespec-client-generator-core";
42
39
  import { Project, SyntaxKind } from "ts-morph";
43
40
  import { buildClientContext } from "./modular/buildClientContext.js";
44
41
  import { emitCodeModel } from "./modular/buildCodeModel.js";
@@ -46,142 +43,260 @@ import {
46
43
  buildRootIndex,
47
44
  buildSubClientIndexFile
48
45
  } from "./modular/buildRootIndex.js";
49
- import { buildModels } from "./modular/emitModels.js";
46
+ import { buildModels, buildModelsOptions } from "./modular/emitModels.js";
50
47
  import { buildOperationFiles } from "./modular/buildOperations.js";
51
48
  import { buildSubpathIndexFile } from "./modular/buildSubpathIndex.js";
52
49
  import { buildClassicalClient } from "./modular/buildClassicalClient.js";
53
50
  import { emitPackage, emitTsConfig } from "./modular/buildProjectFiles.js";
54
51
  import { getRLCClients } from "./utils/clientUtils.js";
52
+ import { join } from "path";
53
+ import { GenerationDirDetail, SdkContext } from "./utils/interfaces.js";
54
+ import { transformRLCOptions } from "./transform/transfromRLCOptions.js";
55
+ import { ModularCodeModel } from "./modular/modularCodeModel.js";
55
56
 
56
- export interface RLCSdkContext extends SdkContext {
57
- options: RLCOptions;
58
- }
57
+ export * from "./lib.js";
59
58
 
60
59
  export async function $onEmit(context: EmitContext) {
60
+ /** Shared status */
61
61
  const program: Program = context.program;
62
- const options: RLCOptions = context.options;
63
- const dpgContext = createSdkContext(context);
64
- const clients = getRLCClients(dpgContext);
65
- const srcPath: string = context.emitterOutputDir;
66
- let count = -1;
67
-
62
+ const emitterOptions: RLCOptions = context.options;
63
+ const dpgContext = createSdkContext(context) as SdkContext;
68
64
  const needUnexpectedHelper: Map<string, boolean> = new Map<string, boolean>();
69
65
  const serviceNameToRlcModelsMap: Map<string, RLCModel> = new Map<
70
66
  string,
71
67
  RLCModel
72
68
  >();
73
- for (const client of clients) {
74
- count++;
75
- const rlcModels = await transformRLCModel(
76
- program,
77
- options,
78
- client,
79
- context.emitterOutputDir,
80
- dpgContext
81
- );
82
- serviceNameToRlcModelsMap.set(client.service.name, rlcModels);
83
- const pathToClear = rlcModels.srcPath;
84
- needUnexpectedHelper.set(client.name, hasUnexpectedHelper(rlcModels));
85
- clearSrcFolder(
86
- pathToClear,
87
- count,
88
- options.multiClient,
89
- options.isModularLibrary
90
- );
91
- await emitModels(rlcModels, program);
92
- await emitContentByBuilder(program, buildClientDefinitions, rlcModels);
93
- await emitContentByBuilder(program, buildResponseTypes, rlcModels);
94
- await emitContentByBuilder(program, buildClient, rlcModels);
95
- await emitContentByBuilder(program, buildParameterTypes, rlcModels);
96
- await emitContentByBuilder(program, buildIsUnexpectedHelper, rlcModels);
97
- await emitContentByBuilder(program, buildIndexFile, rlcModels);
98
- await emitContentByBuilder(program, buildLogger, rlcModels);
99
- await emitContentByBuilder(program, buildTopLevelIndex, rlcModels);
100
- await emitContentByBuilder(program, buildPaginateHelper, rlcModels);
101
- await emitContentByBuilder(program, buildPollingHelper, rlcModels);
102
- // buildSerializeHelper
103
- await emitContentByBuilder(program, buildSerializeHelper, rlcModels);
104
- // build metadata relevant files
105
- await emitContentByBuilder(
106
- program,
107
- [
108
- buildEsLintConfig,
109
- buildRollupConfig,
110
- buildApiExtractorConfig,
111
- buildReadmeFile,
112
- buildPackageFile,
113
- buildTsConfig
114
- ],
115
- rlcModels,
116
- context.emitterOutputDir
117
- );
118
- // build test relevant files
119
- await emitContentByBuilder(
120
- program,
121
- [
122
- buildKarmaConfigFile,
123
- buildEnvFile,
124
- buildEnvBrowserFile,
125
- buildRecordedClientFile,
126
- buildSampleTest
127
- ],
128
- rlcModels,
129
- context.emitterOutputDir
69
+ const rlcCodeModels: RLCModel[] = [];
70
+ let modularCodeModel: ModularCodeModel;
71
+ // 1. Enrich the dpg context with path detail and common options
72
+ await enrichDpgContext();
73
+ // 2. Clear sources folder
74
+ await clearSrcFolder();
75
+ // 3. Generate RLC sources
76
+ await generateRLCSources();
77
+ // 4. Generate Modular sources
78
+ await generateModularSources();
79
+ // 5. Generate metadata and test files
80
+ await generateMetadataAndTest();
81
+
82
+ async function enrichDpgContext() {
83
+ const generationPathDetail: GenerationDirDetail =
84
+ await calculateGenerationDir();
85
+ dpgContext.generationPathDetail = generationPathDetail;
86
+ const options: RLCOptions = transformRLCOptions(emitterOptions, dpgContext);
87
+ dpgContext.rlcOptions = options;
88
+ }
89
+
90
+ async function calculateGenerationDir(): Promise<GenerationDirDetail> {
91
+ const projectRoot = context.emitterOutputDir ?? "";
92
+ let sourcesRoot = join(projectRoot, "src");
93
+ const customizationFolder = join(projectRoot, "sources");
94
+ if (await fsextra.pathExists(customizationFolder)) {
95
+ sourcesRoot = join(customizationFolder, "generated", "src");
96
+ }
97
+ return {
98
+ rootDir: projectRoot,
99
+ metadataDir: projectRoot,
100
+ rlcSourcesDir: join(
101
+ sourcesRoot,
102
+ emitterOptions.isModularLibrary ? "rest" : "" // When generating modular library, RLC has to go under rest folder
103
+ ),
104
+ modularSourcesDir: emitterOptions.isModularLibrary
105
+ ? sourcesRoot
106
+ : undefined
107
+ };
108
+ }
109
+
110
+ async function clearSrcFolder() {
111
+ await fsextra.emptyDir(
112
+ dpgContext.generationPathDetail?.modularSourcesDir ??
113
+ dpgContext.generationPathDetail?.rlcSourcesDir ??
114
+ ""
130
115
  );
131
116
  }
132
117
 
133
- if (options.isModularLibrary) {
134
- // TODO: Emit modular parts of the library
135
- const project = new Project();
136
- const modularCodeModel = emitCodeModel(context, serviceNameToRlcModelsMap, {
137
- casing: "camel"
138
- });
139
- const rootIndexFile = project.createSourceFile(
140
- `${srcPath}/src/index.ts`,
141
- "",
142
- {
143
- overwrite: true
118
+ async function generateRLCSources() {
119
+ const clients = getRLCClients(dpgContext);
120
+ for (const client of clients) {
121
+ const rlcModels = await transformRLCModel(client, dpgContext);
122
+ rlcCodeModels.push(rlcModels);
123
+ serviceNameToRlcModelsMap.set(client.service.name, rlcModels);
124
+ needUnexpectedHelper.set(client.name, hasUnexpectedHelper(rlcModels));
125
+
126
+ await emitModels(rlcModels, program);
127
+ await emitContentByBuilder(program, buildClientDefinitions, rlcModels);
128
+ await emitContentByBuilder(program, buildResponseTypes, rlcModels);
129
+ await emitContentByBuilder(program, buildClient, rlcModels);
130
+ await emitContentByBuilder(program, buildParameterTypes, rlcModels);
131
+ await emitContentByBuilder(program, buildIsUnexpectedHelper, rlcModels);
132
+ await emitContentByBuilder(program, buildIndexFile, rlcModels);
133
+ await emitContentByBuilder(program, buildLogger, rlcModels);
134
+ await emitContentByBuilder(program, buildTopLevelIndex, rlcModels);
135
+ await emitContentByBuilder(program, buildPaginateHelper, rlcModels);
136
+ await emitContentByBuilder(program, buildPollingHelper, rlcModels);
137
+ await emitContentByBuilder(program, buildSerializeHelper, rlcModels);
138
+ }
139
+ }
140
+
141
+ async function generateModularSources() {
142
+ if (emitterOptions.isModularLibrary) {
143
+ // TODO: Emit modular parts of the library
144
+ const modularSourcesRoot =
145
+ dpgContext.generationPathDetail?.modularSourcesDir ?? "src";
146
+ const project = new Project();
147
+ modularCodeModel = emitCodeModel(context, serviceNameToRlcModelsMap, {
148
+ casing: "camel"
149
+ });
150
+ const rootIndexFile = project.createSourceFile(
151
+ `${modularSourcesRoot}/index.ts`,
152
+ "",
153
+ {
154
+ overwrite: true
155
+ }
156
+ );
157
+ for (const subClient of modularCodeModel.clients) {
158
+ let subfolder = "";
159
+ if (modularCodeModel.clients.length > 1) {
160
+ subfolder = normalizeName(
161
+ subClient.name.replace("Client", ""),
162
+ NameType.File
163
+ );
164
+ }
165
+
166
+ buildModels(modularCodeModel, project, modularSourcesRoot, subfolder);
167
+ buildModelsOptions(subClient, project, modularSourcesRoot, subfolder);
168
+ const hasClientUnexpectedHelper =
169
+ needUnexpectedHelper.get(
170
+ subClient.rlcClientName.replace("Context", "Client")
171
+ ) ?? false;
172
+ buildOperationFiles(
173
+ dpgContext,
174
+ subClient,
175
+ project,
176
+ modularSourcesRoot,
177
+ subfolder,
178
+ hasClientUnexpectedHelper
179
+ );
180
+ buildClientContext(
181
+ dpgContext,
182
+ subClient,
183
+ project,
184
+ modularSourcesRoot,
185
+ subfolder
186
+ );
187
+ buildSubpathIndexFile(project, modularSourcesRoot, "models", subfolder);
188
+ buildSubpathIndexFile(project, modularSourcesRoot, "api", subfolder);
189
+ buildClassicalClient(
190
+ dpgContext,
191
+ subClient,
192
+ project,
193
+ modularSourcesRoot,
194
+ subfolder
195
+ );
196
+ if (modularCodeModel.clients.length > 1) {
197
+ buildSubClientIndexFile(
198
+ subClient,
199
+ project,
200
+ modularSourcesRoot,
201
+ subfolder
202
+ );
203
+ }
204
+ buildRootIndex(
205
+ subClient,
206
+ project,
207
+ rootIndexFile,
208
+ modularSourcesRoot,
209
+ subfolder
210
+ );
144
211
  }
145
- );
146
- for (const subClient of modularCodeModel.clients) {
147
- let subfolder = "";
148
- if (modularCodeModel.clients.length > 1) {
149
- subfolder = normalizeName(
150
- subClient.name.replace("Client", ""),
151
- NameType.File
212
+
213
+ removeUnusedInterfaces(project);
214
+
215
+ for (const file of project.getSourceFiles()) {
216
+ await emitContentByBuilder(
217
+ program,
218
+ () => ({ content: file.getFullText(), path: file.getFilePath() }),
219
+ modularCodeModel as any
152
220
  );
221
+ // emitFile(program, { content: hrlcClient.content, path: hrlcClient.path });
153
222
  }
223
+ }
224
+ }
154
225
 
155
- buildClientContext(dpgContext, subClient, project, srcPath, subfolder);
156
- buildModels(modularCodeModel, project, srcPath, subfolder);
157
- buildOperationFiles(
158
- dpgContext,
159
- subClient,
160
- project,
161
- srcPath,
162
- subfolder,
163
- needUnexpectedHelper.get(subClient.name + "Client")
226
+ async function generateMetadataAndTest() {
227
+ if (rlcCodeModels.length === 0 || !rlcCodeModels[0]) {
228
+ return;
229
+ }
230
+ const rlcClient: RLCModel = rlcCodeModels[0];
231
+ const option = dpgContext.rlcOptions!;
232
+ // Generate metadata
233
+ const hasPackageFile = await existsSync(
234
+ join(dpgContext.generationPathDetail?.metadataDir ?? "", "package.json")
235
+ );
236
+ const shouldGenerateMetadata =
237
+ option.generateMetadata === true ||
238
+ (option.generateMetadata === undefined && !hasPackageFile);
239
+ const commonBuilders = [
240
+ buildEsLintConfig,
241
+ buildRollupConfig,
242
+ buildApiExtractorConfig,
243
+ buildReadmeFile
244
+ ];
245
+ if (!option.isModularLibrary) {
246
+ commonBuilders.push(buildPackageFile);
247
+ commonBuilders.push(buildTsConfig);
248
+ }
249
+ if (shouldGenerateMetadata) {
250
+ // build metadata relevant files
251
+ await emitContentByBuilder(
252
+ program,
253
+ commonBuilders,
254
+ rlcClient,
255
+ dpgContext.generationPathDetail?.metadataDir
164
256
  );
165
- buildSubpathIndexFile(project, srcPath, "models", subfolder);
166
- buildSubpathIndexFile(project, srcPath, "api", subfolder);
167
- buildClassicalClient(dpgContext, subClient, project, srcPath, subfolder);
168
- if (modularCodeModel.clients.length > 1) {
169
- buildSubClientIndexFile(subClient, project, srcPath, subfolder);
257
+
258
+ if (option.isModularLibrary) {
259
+ const project = new Project();
260
+ emitPackage(
261
+ project,
262
+ dpgContext.generationPathDetail?.metadataDir ?? "",
263
+ modularCodeModel
264
+ );
265
+ emitTsConfig(
266
+ project,
267
+ dpgContext.generationPathDetail?.metadataDir ?? "",
268
+ modularCodeModel
269
+ );
270
+ for (const file of project.getSourceFiles()) {
271
+ await emitContentByBuilder(
272
+ program,
273
+ () => ({ content: file.getFullText(), path: file.getFilePath() }),
274
+ modularCodeModel as any
275
+ );
276
+ }
170
277
  }
171
- buildRootIndex(subClient, project, rootIndexFile, srcPath, subfolder);
172
278
  }
173
279
 
174
- emitPackage(project, srcPath, modularCodeModel);
175
- emitTsConfig(project, srcPath, modularCodeModel);
176
- removeUnusedInterfaces(project);
177
-
178
- for (const file of project.getSourceFiles()) {
280
+ // Generate test relevant files
281
+ const hasTestFolder = await fsextra.pathExists(
282
+ join(dpgContext.generationPathDetail?.metadataDir ?? "", "test")
283
+ );
284
+ const shouldGenerateTest =
285
+ option.generateTest === true ||
286
+ (option.generateTest === undefined && !hasTestFolder);
287
+ if (shouldGenerateTest) {
179
288
  await emitContentByBuilder(
180
289
  program,
181
- () => ({ content: file.getFullText(), path: file.getFilePath() }),
182
- modularCodeModel as any
290
+ [
291
+ buildKarmaConfigFile,
292
+ buildEnvFile,
293
+ buildEnvBrowserFile,
294
+ buildRecordedClientFile,
295
+ buildSampleTest
296
+ ],
297
+ rlcClient,
298
+ dpgContext.generationPathDetail?.metadataDir
183
299
  );
184
- // emitFile(program, { content: hrlcClient.content, path: hrlcClient.path });
185
300
  }
186
301
  }
187
302
  }
@@ -223,7 +338,9 @@ export function removeUnusedInterfaces(project: Project) {
223
338
  });
224
339
 
225
340
  // Get the index.ts file
226
- const indexFiles = project.getSourceFiles("**/index.ts"); // Adjust the path to your index.ts file
341
+ const indexFiles = project.getSourceFiles().filter((file) => {
342
+ return file.getFilePath().endsWith("index.ts");
343
+ }); // Adjust the path to your index.ts file
227
344
  // to make sure the top level index file is in the last
228
345
  const sortedIndexFiles = indexFiles.sort((idx1, idx2) => {
229
346
  return (
@@ -267,18 +384,3 @@ export function removeUnusedInterfaces(project: Project) {
267
384
  interfaceDeclaration.interfaceDeclaration.remove();
268
385
  });
269
386
  }
270
-
271
- function clearSrcFolder(
272
- srcPath: string,
273
- count: number,
274
- isMultiClient: boolean = false,
275
- isModularLibrary: boolean = false
276
- ) {
277
- fsextra.emptyDirSync(srcPath);
278
- if ((isMultiClient || isModularLibrary) && count === 0) {
279
- const folderPath = path.join(
280
- srcPath.substring(0, srcPath.lastIndexOf(path.sep + "src") + 4)
281
- );
282
- fsextra.emptyDirSync(folderPath);
283
- }
284
- }
package/src/lib.ts CHANGED
@@ -30,9 +30,9 @@ export const RLCOptionsSchema: JSONSchemaType<RLCOptions> = {
30
30
  scopeName: { type: "string", nullable: true },
31
31
  nameWithoutScope: { type: "string", nullable: true },
32
32
  description: { type: "string", nullable: true },
33
- version: { type: "string", nullable: false }
33
+ version: { type: "string", nullable: true }
34
34
  },
35
- required: ["name", "version"],
35
+ required: ["name"],
36
36
  nullable: true
37
37
  },
38
38
  addCredentials: { type: "boolean", nullable: true },
@@ -42,6 +42,8 @@ export const RLCOptionsSchema: JSONSchemaType<RLCOptions> = {
42
42
  items: { type: "string" }
43
43
  },
44
44
  credentialKeyHeaderName: { type: "string", nullable: true },
45
+ customHttpAuthHeaderName: { type: "string", nullable: true },
46
+ customHttpAuthSharedKeyPrefix: { type: "string", nullable: true },
45
47
  generateMetadata: { type: "boolean", nullable: true },
46
48
  generateTest: { type: "boolean", nullable: true },
47
49
  generateSample: { type: "boolean", nullable: true },
@@ -14,7 +14,8 @@ import { getClientName } from "./helpers/namingHelpers.js";
14
14
  import { getOperationFunction } from "./helpers/operationHelpers.js";
15
15
  import { Client } from "./modularCodeModel.js";
16
16
  import { isRLCMultiEndpoint } from "../utils/clientUtils.js";
17
- import { SdkContext } from "@azure-tools/typespec-client-generator-core";
17
+ import { getDocsFromDescription } from "./helpers/docsHelpers.js";
18
+ import { SdkContext } from "../utils/interfaces.js";
18
19
 
19
20
  export function buildClassicalClient(
20
21
  dpgContext: SdkContext,
@@ -29,7 +30,7 @@ export function buildClassicalClient(
29
30
  const params = getClientParameters(client);
30
31
 
31
32
  const clientFile = project.createSourceFile(
32
- `${srcPath}/src/${
33
+ `${srcPath}/${
33
34
  subfolder !== "" ? subfolder + "/" : ""
34
35
  }${classicalClientname}.ts`
35
36
  );
@@ -61,7 +62,7 @@ export function buildClassicalClient(
61
62
 
62
63
  // TODO: We may need to generate constructor overloads at some point. Here we'd do that.
63
64
  const constructor = clientClass.addConstructor({
64
- docs: [description],
65
+ docs: getDocsFromDescription(description),
65
66
  parameters: params
66
67
  });
67
68
  constructor.addStatements([
@@ -84,7 +85,7 @@ function importAllApis(
84
85
  ) {
85
86
  const project = clientFile.getProject();
86
87
  const apiModels = project.getSourceFile(
87
- `${srcPath}/src/${subfolder !== "" ? subfolder + "/" : ""}api/index.ts`
88
+ `${srcPath}/${subfolder !== "" ? subfolder + "/" : ""}api/index.ts`
88
89
  );
89
90
 
90
91
  if (!apiModels) {
@@ -106,7 +107,7 @@ function importAllModels(
106
107
  ) {
107
108
  const project = clientFile.getProject();
108
109
  const apiModels = project.getSourceFile(
109
- `${srcPath}/src/${subfolder !== "" ? subfolder + "/" : ""}models/models.ts`
110
+ `${srcPath}/${subfolder !== "" ? subfolder + "/" : ""}models/models.ts`
110
111
  );
111
112
 
112
113
  if (!apiModels) {
@@ -115,13 +116,15 @@ function importAllModels(
115
116
 
116
117
  const exported = [...apiModels.getExportedDeclarations().keys()];
117
118
 
118
- clientFile.addImportDeclaration({
119
- moduleSpecifier: `./models/models.js`,
120
- namedImports: exported
121
- });
119
+ if (exported.length > 0) {
120
+ clientFile.addImportDeclaration({
121
+ moduleSpecifier: `./models/models.js`,
122
+ namedImports: exported
123
+ });
124
+ }
122
125
 
123
126
  const apiModelsOptions = project.getSourceFile(
124
- `${srcPath}/src/${subfolder !== "" ? subfolder + "/" : ""}models/options.ts`
127
+ `${srcPath}/${subfolder !== "" ? subfolder + "/" : ""}models/options.ts`
125
128
  );
126
129
 
127
130
  if (!apiModelsOptions) {
@@ -150,6 +153,10 @@ function buildClientOperationGroups(
150
153
  clientClass: ClassDeclaration,
151
154
  subfolder: string
152
155
  ) {
156
+ const operationMap = new Map<
157
+ OptionalKind<FunctionDeclarationStructure>,
158
+ string | undefined
159
+ >();
153
160
  for (const operationGroup of client.operationGroups) {
154
161
  const operationGroupName = toCamelCase(operationGroup.propertyName);
155
162
  let clientType = "Client";
@@ -157,9 +164,11 @@ function buildClientOperationGroups(
157
164
  clientType = `Client.${clientClass.getName()}`;
158
165
  }
159
166
  const operationDeclarations: OptionalKind<FunctionDeclarationStructure>[] =
160
- operationGroup.operations.map((operation) =>
161
- getOperationFunction(operation, clientType)
162
- );
167
+ operationGroup.operations.map((operation) => {
168
+ const declarations = getOperationFunction(operation, clientType);
169
+ operationMap.set(declarations, operation.oriName);
170
+ return declarations;
171
+ });
163
172
 
164
173
  if (operationGroupName && operationGroupName !== "") {
165
174
  clientClass.addProperty({
@@ -167,9 +176,11 @@ function buildClientOperationGroups(
167
176
  initializer: `
168
177
  {
169
178
  ${operationDeclarations.map((d) => {
170
- return `${d.name}: (${d.parameters
179
+ return `${getClassicalMethodName(d)}: (${d.parameters
171
180
  ?.filter((p) => p.name !== "context")
172
- .map((p) => p.name + ": " + p.type)
181
+ .map(
182
+ (p) => p.name + (p.name === "options" ? "?" : "") + ": " + p.type
183
+ )
173
184
  .join(",")}): ${d.returnType} => {return ${d.name}(${[
174
185
  "this._client",
175
186
  ...[d.parameters?.map((p) => p.name).filter((p) => p !== "context")]
@@ -183,7 +194,7 @@ function buildClientOperationGroups(
183
194
  operationDeclarations.map((d) => {
184
195
  const method: MethodDeclarationStructure = {
185
196
  docs: d.docs,
186
- name: d.name ?? "FIXME",
197
+ name: getClassicalMethodName(d),
187
198
  kind: StructureKind.Method,
188
199
  returnType: d.returnType,
189
200
  parameters: d.parameters?.filter((p) => p.name !== "context"),
@@ -200,4 +211,10 @@ function buildClientOperationGroups(
200
211
  );
201
212
  }
202
213
  }
214
+
215
+ function getClassicalMethodName(
216
+ declaration: OptionalKind<FunctionDeclarationStructure>
217
+ ) {
218
+ return operationMap.get(declaration) ?? declaration.name ?? "FIXME";
219
+ }
203
220
  }