@azure-tools/typespec-ts 0.46.0 → 0.46.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.
- package/CHANGELOG.md +9 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +30 -7
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib.d.ts.map +1 -1
- package/dist/src/lib.js +2 -1
- package/dist/src/lib.js.map +1 -1
- package/dist/src/modular/emitModels.d.ts.map +1 -1
- package/dist/src/modular/emitModels.js +3 -2
- package/dist/src/modular/emitModels.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +6 -2
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/transform/transfromRLCOptions.d.ts.map +1 -1
- package/dist/src/transform/transfromRLCOptions.js +10 -12
- package/dist/src/transform/transfromRLCOptions.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -23
- package/src/index.ts +38 -1
- package/src/lib.ts +2 -1
- package/src/modular/emitModels.ts +5 -6
- package/src/modular/helpers/operationHelpers.ts +8 -2
- package/src/transform/transfromRLCOptions.ts +7 -10
- package/static/static-helpers/pagingHelpers.ts +5 -1
- package/static/static-helpers/urlTemplate.ts +18 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure-tools/typespec-ts",
|
|
3
|
-
"version": "0.46.
|
|
3
|
+
"version": "0.46.1",
|
|
4
4
|
"description": "An experimental TypeSpec emitter for TypeScript RLC",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@azure-rest/core-client": "^2.3.1",
|
|
21
|
-
"@typespec/http-specs": "0.1.0-alpha.
|
|
22
|
-
"@typespec/spector": "0.1.0-alpha.
|
|
23
|
-
"@typespec/spec-api": "0.1.0-alpha.
|
|
24
|
-
"@typespec/tspd": "0.73.
|
|
25
|
-
"@azure-tools/azure-http-specs": "0.1.0-alpha.
|
|
26
|
-
"@azure-tools/typespec-autorest": "^0.
|
|
27
|
-
"@azure-tools/typespec-azure-core": "^0.
|
|
28
|
-
"@azure-tools/typespec-azure-resource-manager": "^0.
|
|
29
|
-
"@azure-tools/typespec-client-generator-core": "^0.
|
|
21
|
+
"@typespec/http-specs": "0.1.0-alpha.29-dev.2",
|
|
22
|
+
"@typespec/spector": "0.1.0-alpha.21-dev.1",
|
|
23
|
+
"@typespec/spec-api": "0.1.0-alpha.11-dev.0",
|
|
24
|
+
"@typespec/tspd": "0.73.1",
|
|
25
|
+
"@azure-tools/azure-http-specs": "0.1.0-alpha.33-dev.0",
|
|
26
|
+
"@azure-tools/typespec-autorest": "^0.62.0",
|
|
27
|
+
"@azure-tools/typespec-azure-core": "^0.62.0",
|
|
28
|
+
"@azure-tools/typespec-azure-resource-manager": "^0.62.0",
|
|
29
|
+
"@azure-tools/typespec-client-generator-core": "^0.62.0",
|
|
30
30
|
"@azure/abort-controller": "^2.1.2",
|
|
31
31
|
"@azure/core-auth": "^1.6.0",
|
|
32
32
|
"@azure/core-lro": "^3.1.0",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
"@types/node": "^18.0.0",
|
|
42
42
|
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
|
43
43
|
"@typescript-eslint/parser": "^8.28.0",
|
|
44
|
-
"@typespec/compiler": "^1.
|
|
45
|
-
"@typespec/http": "^1.
|
|
46
|
-
"@typespec/openapi": "^1.
|
|
47
|
-
"@typespec/rest": "^0.
|
|
44
|
+
"@typespec/compiler": "^1.6.0",
|
|
45
|
+
"@typespec/http": "^1.6.0",
|
|
46
|
+
"@typespec/openapi": "^1.6.0",
|
|
47
|
+
"@typespec/rest": "^0.76.0",
|
|
48
48
|
"@typespec/ts-http-runtime": "^0.1.0",
|
|
49
|
-
"@typespec/versioning": "^0.
|
|
49
|
+
"@typespec/versioning": "^0.76.0",
|
|
50
50
|
"chai": "^4.3.6",
|
|
51
51
|
"chalk": "^4.0.0",
|
|
52
52
|
"cross-env": "^7.0.3",
|
|
@@ -68,16 +68,16 @@
|
|
|
68
68
|
"js-yaml": "^4.1.0"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@azure-tools/typespec-azure-core": "^0.
|
|
72
|
-
"@azure-tools/typespec-client-generator-core": "^0.
|
|
73
|
-
"@typespec/compiler": "^1.
|
|
74
|
-
"@typespec/http": "^1.
|
|
75
|
-
"@typespec/rest": "^0.
|
|
76
|
-
"@typespec/versioning": "^0.
|
|
77
|
-
"@typespec/xml": "^0.
|
|
71
|
+
"@azure-tools/typespec-azure-core": "^0.62.0",
|
|
72
|
+
"@azure-tools/typespec-client-generator-core": "^0.62.0",
|
|
73
|
+
"@typespec/compiler": "^1.6.0",
|
|
74
|
+
"@typespec/http": "^1.6.0",
|
|
75
|
+
"@typespec/rest": "^0.76.0",
|
|
76
|
+
"@typespec/versioning": "^0.76.0",
|
|
77
|
+
"@typespec/xml": "^0.76.0"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@azure-tools/rlc-common": "^0.46.
|
|
80
|
+
"@azure-tools/rlc-common": "^0.46.1",
|
|
81
81
|
"fs-extra": "^11.1.0",
|
|
82
82
|
"lodash": "^4.17.21",
|
|
83
83
|
"prettier": "^3.3.3",
|
package/src/index.ts
CHANGED
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
buildPollingHelper,
|
|
36
36
|
buildPaginateHelper as buildRLCPaginateHelper,
|
|
37
37
|
buildReadmeFile,
|
|
38
|
+
updateReadmeFile,
|
|
38
39
|
buildRecordedClientFile,
|
|
39
40
|
buildResponseTypes,
|
|
40
41
|
buildRollupConfig,
|
|
@@ -162,6 +163,8 @@ export async function $onEmit(context: EmitContext) {
|
|
|
162
163
|
// 2. Generate RLC code model
|
|
163
164
|
// TODO: skip this step in modular once modular generator is sufficiently decoupled
|
|
164
165
|
await buildRLCCodeModels();
|
|
166
|
+
// 3. Clear samples-dev folder if generateSample is true
|
|
167
|
+
await clearSamplesDevFolder();
|
|
165
168
|
|
|
166
169
|
// 4. Generate sources
|
|
167
170
|
if (emitterOptions["is-modular-library"]) {
|
|
@@ -236,6 +239,18 @@ export async function $onEmit(context: EmitContext) {
|
|
|
236
239
|
);
|
|
237
240
|
}
|
|
238
241
|
|
|
242
|
+
async function clearSamplesDevFolder() {
|
|
243
|
+
if (emitterOptions["generate-sample"] === true) {
|
|
244
|
+
const samplesDevPath = join(
|
|
245
|
+
dpgContext.generationPathDetail?.rootDir ?? "",
|
|
246
|
+
"samples-dev"
|
|
247
|
+
);
|
|
248
|
+
if (await fsextra.pathExists(samplesDevPath)) {
|
|
249
|
+
await fsextra.emptyDir(samplesDevPath);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
239
254
|
async function buildRLCCodeModels() {
|
|
240
255
|
const clients = getRLCClients(dpgContext);
|
|
241
256
|
for (const client of clients) {
|
|
@@ -408,6 +423,11 @@ export async function $onEmit(context: EmitContext) {
|
|
|
408
423
|
"package.json"
|
|
409
424
|
);
|
|
410
425
|
const hasPackageFile = await existsSync(existingPackageFilePath);
|
|
426
|
+
const existingReadmeFilePath = join(
|
|
427
|
+
dpgContext.generationPathDetail?.metadataDir ?? "",
|
|
428
|
+
"README.md"
|
|
429
|
+
);
|
|
430
|
+
const hasReadmeFile = await existsSync(existingReadmeFilePath);
|
|
411
431
|
const shouldGenerateMetadata =
|
|
412
432
|
option.generateMetadata === true || !hasPackageFile;
|
|
413
433
|
const existingTestFolderPath = join(
|
|
@@ -507,12 +527,29 @@ export async function $onEmit(context: EmitContext) {
|
|
|
507
527
|
}
|
|
508
528
|
} else if (hasPackageFile) {
|
|
509
529
|
// update existing package.json file with correct dependencies
|
|
530
|
+
let modularPackageInfo = {};
|
|
531
|
+
if (option.isModularLibrary) {
|
|
532
|
+
modularPackageInfo = {
|
|
533
|
+
exports: getModuleExports(context, modularEmitterOptions)
|
|
534
|
+
};
|
|
535
|
+
}
|
|
510
536
|
await emitContentByBuilder(
|
|
511
537
|
program,
|
|
512
|
-
(model) =>
|
|
538
|
+
(model) =>
|
|
539
|
+
updatePackageFile(model, existingPackageFilePath, modularPackageInfo),
|
|
513
540
|
rlcClient,
|
|
514
541
|
dpgContext.generationPathDetail?.metadataDir
|
|
515
542
|
);
|
|
543
|
+
|
|
544
|
+
// update existing README.md file if it exists
|
|
545
|
+
if (hasReadmeFile) {
|
|
546
|
+
await emitContentByBuilder(
|
|
547
|
+
program,
|
|
548
|
+
(model) => updateReadmeFile(model, existingReadmeFilePath),
|
|
549
|
+
rlcClient,
|
|
550
|
+
dpgContext.generationPathDetail?.metadataDir
|
|
551
|
+
);
|
|
552
|
+
}
|
|
516
553
|
}
|
|
517
554
|
if (isAzureFlavor) {
|
|
518
555
|
await emitContentByBuilder(
|
package/src/lib.ts
CHANGED
|
@@ -102,7 +102,8 @@ export const RLCOptionsSchema: JSONSchemaType<EmitterOptions> = {
|
|
|
102
102
|
scopeName: { type: "string", nullable: true },
|
|
103
103
|
nameWithoutScope: { type: "string", nullable: true },
|
|
104
104
|
description: { type: "string", nullable: true },
|
|
105
|
-
version: { type: "string", nullable: true }
|
|
105
|
+
version: { type: "string", nullable: true },
|
|
106
|
+
isVersionUserProvided: { type: "boolean", nullable: true }
|
|
106
107
|
},
|
|
107
108
|
required: ["name"],
|
|
108
109
|
nullable: true,
|
|
@@ -112,13 +112,12 @@ export function emitTypes(
|
|
|
112
112
|
sourceFile = outputProject.getSourceFile(filepath);
|
|
113
113
|
if (!sourceFile) {
|
|
114
114
|
sourceFile = outputProject.createSourceFile(filepath);
|
|
115
|
-
sourceFile.addStatements(
|
|
116
|
-
|
|
117
|
-
*
|
|
118
|
-
* Disable this rule for deserializer functions which require 'any' for raw JSON input.
|
|
115
|
+
sourceFile.addStatements(`/**
|
|
116
|
+
* This file contains only generated model types and their (de)serializers.
|
|
117
|
+
* Disable the following rules for internal models with '_' prefix and deserializers which require 'any' for raw JSON input.
|
|
119
118
|
*/
|
|
120
|
-
/* eslint-disable @typescript-eslint/
|
|
121
|
-
|
|
119
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
120
|
+
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */`);
|
|
122
121
|
}
|
|
123
122
|
emitType(context, type, sourceFile);
|
|
124
123
|
}
|
|
@@ -637,19 +637,25 @@ function getPagingOnlyOperationFunction(
|
|
|
637
637
|
return property.name;
|
|
638
638
|
})
|
|
639
639
|
.join(".");
|
|
640
|
+
|
|
641
|
+
// Check for nextLinkVerb from TCGC pagingMetadata (supports @Legacy.nextLinkVerb decorator)
|
|
642
|
+
const nextLinkMethod = operation.pagingMetadata.nextLinkVerb;
|
|
643
|
+
|
|
640
644
|
if (itemName) {
|
|
641
645
|
options.push(`itemName: "${itemName}"`);
|
|
642
646
|
}
|
|
643
647
|
if (nextLinkName) {
|
|
644
648
|
options.push(`nextLinkName: "${nextLinkName}"`);
|
|
645
649
|
}
|
|
650
|
+
if (nextLinkMethod && nextLinkMethod !== "GET") {
|
|
651
|
+
options.push(`nextLinkMethod: "${nextLinkMethod}"`);
|
|
652
|
+
}
|
|
646
653
|
statements.push(
|
|
647
654
|
`return ${buildPagedAsyncIteratorReference}(
|
|
648
655
|
context,
|
|
649
656
|
() => _${name}Send(${parameters.map((p) => p.name).join(", ")}),
|
|
650
657
|
_${name}Deserialize,
|
|
651
|
-
${getExpectedStatuses(operation)},
|
|
652
|
-
${options.length > 0 ? `{${options.join(", ")}}` : ``}
|
|
658
|
+
${getExpectedStatuses(operation)}${options.length > 0 ? `,\n {${options.join(", ")}}` : ""}
|
|
653
659
|
);`
|
|
654
660
|
);
|
|
655
661
|
|
|
@@ -5,8 +5,7 @@ import {
|
|
|
5
5
|
PackageDetails,
|
|
6
6
|
PackageFlavor,
|
|
7
7
|
RLCOptions,
|
|
8
|
-
ServiceInfo
|
|
9
|
-
isAzurePackage
|
|
8
|
+
ServiceInfo
|
|
10
9
|
} from "@azure-tools/rlc-common";
|
|
11
10
|
import { getHttpOperationWithCache } from "@azure-tools/typespec-client-generator-core";
|
|
12
11
|
import { getDoc, NoTarget, Program } from "@typespec/compiler";
|
|
@@ -34,13 +33,7 @@ export function transformRLCOptions(
|
|
|
34
33
|
emitterOptions,
|
|
35
34
|
dpgContext.generationPathDetail?.rootDir ?? ""
|
|
36
35
|
);
|
|
37
|
-
if (
|
|
38
|
-
!isAzurePackage({ options }) &&
|
|
39
|
-
emitterOptions["is-modular-library"] !== false
|
|
40
|
-
) {
|
|
41
|
-
options.isModularLibrary = true;
|
|
42
|
-
}
|
|
43
|
-
if (dpgContext.arm && emitterOptions["is-modular-library"] !== false) {
|
|
36
|
+
if (emitterOptions["is-modular-library"] !== false) {
|
|
44
37
|
options.isModularLibrary = true;
|
|
45
38
|
}
|
|
46
39
|
const batch = getRLCClients(dpgContext);
|
|
@@ -302,6 +295,9 @@ function buildPackageDetails(
|
|
|
302
295
|
nameWithoutScope: "unamedpackage",
|
|
303
296
|
version: "1.0.0-beta.1"
|
|
304
297
|
};
|
|
298
|
+
const isVersionUserProvided = Boolean(
|
|
299
|
+
emitterOptions["package-details"]?.version
|
|
300
|
+
);
|
|
305
301
|
const packageDetails: PackageDetails = {
|
|
306
302
|
...emitterOptions["package-details"],
|
|
307
303
|
name:
|
|
@@ -310,7 +306,8 @@ function buildPackageDetails(
|
|
|
310
306
|
emitterOptions?.title ?? getDefaultService(program)?.title ?? "",
|
|
311
307
|
NameType.Class
|
|
312
308
|
),
|
|
313
|
-
version: emitterOptions["package-details"]?.version ?? "1.0.0-beta.1"
|
|
309
|
+
version: emitterOptions["package-details"]?.version ?? "1.0.0-beta.1",
|
|
310
|
+
isVersionUserProvided
|
|
314
311
|
};
|
|
315
312
|
if (emitterOptions["package-details"]?.name) {
|
|
316
313
|
const nameParts = emitterOptions["package-details"]?.name.split("/");
|
|
@@ -90,6 +90,7 @@ export interface PagedResult<
|
|
|
90
90
|
export interface BuildPagedAsyncIteratorOptions {
|
|
91
91
|
itemName?: string;
|
|
92
92
|
nextLinkName?: string;
|
|
93
|
+
nextLinkMethod?: "GET" | "POST";
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
/**
|
|
@@ -109,12 +110,15 @@ export function buildPagedAsyncIterator<
|
|
|
109
110
|
): PagedAsyncIterableIterator<TElement, TPage, TPageSettings> {
|
|
110
111
|
const itemName = options.itemName ?? "value";
|
|
111
112
|
const nextLinkName = options.nextLinkName ?? "nextLink";
|
|
113
|
+
const nextLinkMethod = options.nextLinkMethod ?? "GET";
|
|
112
114
|
const pagedResult: PagedResult<TElement, TPage, TPageSettings> = {
|
|
113
115
|
getPage: async (pageLink?: string) => {
|
|
114
116
|
const result =
|
|
115
117
|
pageLink === undefined
|
|
116
118
|
? await getInitialResponse()
|
|
117
|
-
:
|
|
119
|
+
: nextLinkMethod === "POST"
|
|
120
|
+
? await client.pathUnchecked(pageLink).post()
|
|
121
|
+
: await client.pathUnchecked(pageLink).get();
|
|
118
122
|
checkPagingRequest(result, expectedStatuses);
|
|
119
123
|
const results = await processResponseBody(result as TResponse);
|
|
120
124
|
const nextLink = getNextLink(results, nextLinkName);
|
|
@@ -177,7 +177,7 @@ export function expandUrlTemplate(
|
|
|
177
177
|
context: Record<string, any>,
|
|
178
178
|
option?: UrlTemplateOptions
|
|
179
179
|
): string {
|
|
180
|
-
|
|
180
|
+
const result = template.replace(/\{([^{}]+)\}|([^{}]+)/g, (_, expr, text) => {
|
|
181
181
|
if (!expr) {
|
|
182
182
|
return encodeReservedComponent(text);
|
|
183
183
|
}
|
|
@@ -207,4 +207,21 @@ export function expandUrlTemplate(
|
|
|
207
207
|
}
|
|
208
208
|
return result.join("");
|
|
209
209
|
});
|
|
210
|
+
|
|
211
|
+
return normalizeUnreserved(result);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Normalize an expanded URI by decoding percent-encoded unreserved characters.
|
|
216
|
+
* RFC 3986 unreserved: "-" / "." / "~"
|
|
217
|
+
*/
|
|
218
|
+
function normalizeUnreserved(uri: string): string {
|
|
219
|
+
return uri.replace(/%([0-9A-Fa-f]{2})/g, (match, hex) => {
|
|
220
|
+
const char = String.fromCharCode(parseInt(hex, 16));
|
|
221
|
+
// Decode only if it's unreserved
|
|
222
|
+
if (/[\-.~]/.test(char)) {
|
|
223
|
+
return char;
|
|
224
|
+
}
|
|
225
|
+
return match; // leave other encodings intact
|
|
226
|
+
});
|
|
210
227
|
}
|