@azure-tools/typespec-ts 0.45.1-alpha.20251105.1 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/src/framework/hooks/binder.d.ts.map +1 -1
- package/dist/src/framework/hooks/binder.js +10 -4
- package/dist/src/framework/hooks/binder.js.map +1 -1
- package/dist/src/framework/load-static-helpers.js +1 -1
- package/dist/src/framework/load-static-helpers.js.map +1 -1
- package/dist/src/modular/helpers/clientHelpers.js +6 -4
- package/dist/src/modular/helpers/clientHelpers.js.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.d.ts.map +1 -1
- package/dist/src/modular/helpers/operationHelpers.js +13 -6
- package/dist/src/modular/helpers/operationHelpers.js.map +1 -1
- package/dist/src/modular/static-helpers-metadata.d.ts +5 -0
- package/dist/src/modular/static-helpers-metadata.d.ts.map +1 -1
- package/dist/src/modular/static-helpers-metadata.js +5 -0
- package/dist/src/modular/static-helpers-metadata.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/framework/hooks/binder.ts +12 -4
- package/src/framework/load-static-helpers.ts +1 -1
- package/src/modular/helpers/clientHelpers.ts +5 -5
- package/src/modular/helpers/operationHelpers.ts +14 -6
- package/src/modular/static-helpers-metadata.ts +5 -0
- package/static/static-helpers/serialization/get-binary-response-browser.mts +20 -0
- package/static/static-helpers/serialization/get-binary-response.ts +25 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure-tools/typespec-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.0",
|
|
4
4
|
"description": "An experimental TypeSpec emitter for TypeScript RLC",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"@typespec/xml": "^0.75.0"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@azure-tools/rlc-common": "0.
|
|
80
|
+
"@azure-tools/rlc-common": "^0.46.0",
|
|
81
81
|
"fs-extra": "^11.1.0",
|
|
82
82
|
"lodash": "^4.17.21",
|
|
83
83
|
"prettier": "^3.3.3",
|
|
@@ -303,7 +303,7 @@ class BinderImp implements Binder {
|
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
private cleanUnreferencedHelpers(sourceRoot: string) {
|
|
306
|
-
const
|
|
306
|
+
const usedHelperNames: string[] = [];
|
|
307
307
|
for (const helper of this.staticHelpers.values()) {
|
|
308
308
|
const sourceFile = helper[SourceFileSymbol];
|
|
309
309
|
if (!sourceFile) {
|
|
@@ -315,16 +315,24 @@ class BinderImp implements Binder {
|
|
|
315
315
|
const referencedHelper = this.references.get(refkey(helper));
|
|
316
316
|
|
|
317
317
|
if (referencedHelper?.size) {
|
|
318
|
-
|
|
318
|
+
usedHelperNames.push(sourceFile.getBaseNameWithoutExtension());
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
function isFileUnused(file: SourceFile) {
|
|
323
|
+
const name = file.getBaseNameWithoutExtension();
|
|
324
|
+
|
|
325
|
+
// If one of the used helpers' name is a prefix of this file, the file likely represents a platform-specific implementation of the helper
|
|
326
|
+
// so it should be marked as used even if the file has no direct references.
|
|
327
|
+
return !usedHelperNames.some((s) => name.startsWith(s));
|
|
328
|
+
}
|
|
329
|
+
|
|
322
330
|
this.project
|
|
323
331
|
//normalizae the final path to adapt to different systems
|
|
324
332
|
.getSourceFiles(
|
|
325
|
-
normalizePath(path.join(sourceRoot, "static-helpers
|
|
333
|
+
normalizePath(path.join(sourceRoot, "static-helpers/**/*.*ts"))
|
|
326
334
|
)
|
|
327
|
-
.filter(
|
|
335
|
+
.filter(isFileUnused)
|
|
328
336
|
.forEach((helperFile) => helperFile.delete());
|
|
329
337
|
}
|
|
330
338
|
}
|
|
@@ -73,14 +73,15 @@ export function getClientParameters(
|
|
|
73
73
|
const hasDefaultValue = (p: SdkParameter) =>
|
|
74
74
|
p.clientDefaultValue || p.__raw?.defaultValue || p.type.kind === "constant";
|
|
75
75
|
const isRequired = (p: SdkParameter) =>
|
|
76
|
-
|
|
77
|
-
(
|
|
76
|
+
// Special case: when apiVersionAsRequired is true, apiVersion should always be considered required
|
|
77
|
+
(options.apiVersionAsRequired && p.isApiVersionParam) ||
|
|
78
|
+
(!p.optional &&
|
|
79
|
+
!hasDefaultValue(p) &&
|
|
78
80
|
!(
|
|
79
81
|
p.type.kind === "endpoint" &&
|
|
80
82
|
p.type.templateArguments[0] &&
|
|
81
83
|
hasDefaultValue(p.type.templateArguments[0])
|
|
82
|
-
))
|
|
83
|
-
(options.apiVersionAsRequired && p.isApiVersionParam));
|
|
84
|
+
));
|
|
84
85
|
const isOptional = (p: SdkParameter) => p.optional || hasDefaultValue(p);
|
|
85
86
|
const skipCredentials = (p: SdkParameter) => p.kind !== "credential";
|
|
86
87
|
const skipMethodParam = (p: SdkParameter) => p.kind !== "method";
|
|
@@ -98,7 +99,6 @@ export function getClientParameters(
|
|
|
98
99
|
const params = clientParams.filter((p) =>
|
|
99
100
|
filters.every((filter) => !filter || filter(p))
|
|
100
101
|
);
|
|
101
|
-
|
|
102
102
|
return params;
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -8,6 +8,7 @@ import { NoTarget, Program } from "@typespec/compiler";
|
|
|
8
8
|
import {
|
|
9
9
|
PagingHelpers,
|
|
10
10
|
PollingHelpers,
|
|
11
|
+
SerializationHelpers,
|
|
11
12
|
UrlTemplateHelpers
|
|
12
13
|
} from "../static-helpers-metadata.js";
|
|
13
14
|
import {
|
|
@@ -472,11 +473,18 @@ export function getOperationFunction(
|
|
|
472
473
|
};
|
|
473
474
|
|
|
474
475
|
const statements: string[] = [];
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
)
|
|
476
|
+
|
|
477
|
+
const parameterList = parameters.map((p) => p.name).join(", ");
|
|
478
|
+
// Special case for binary-only bodies: use helper to call streaming methods so that Core doesn't poison the response body by
|
|
479
|
+
// doing a UTF-8 decode on the raw bytes.
|
|
480
|
+
if (response?.type?.kind === "bytes" && response.type.encode === "bytes") {
|
|
481
|
+
statements.push(`const streamableMethod = _${name}Send(${parameterList});`);
|
|
482
|
+
statements.push(
|
|
483
|
+
`const result = await ${resolveReference(SerializationHelpers.getBinaryResponse)}(streamableMethod);`
|
|
484
|
+
);
|
|
485
|
+
} else {
|
|
486
|
+
statements.push(`const result = await _${name}Send(${parameterList});`);
|
|
487
|
+
}
|
|
480
488
|
statements.push(`return _${name}Deserialize(result);`);
|
|
481
489
|
|
|
482
490
|
return {
|
|
@@ -1577,7 +1585,7 @@ export function getExpectedStatuses(operation: ServiceOperation): string {
|
|
|
1577
1585
|
let statusCodes = operation.operation.responses.map((x) => x.statusCodes);
|
|
1578
1586
|
// LROs may call the same path but with GET to get the operation status.
|
|
1579
1587
|
if (isLroOnlyOperation(operation) && operation.operation.verb !== "get") {
|
|
1580
|
-
statusCodes = Array.from(new Set([...statusCodes, 200, 202]));
|
|
1588
|
+
statusCodes = Array.from(new Set([...statusCodes, 200, 201, 202]));
|
|
1581
1589
|
}
|
|
1582
1590
|
|
|
1583
1591
|
return `[${statusCodes.map((x) => `"${x}"`).join(", ")}]`;
|
|
@@ -28,6 +28,11 @@ export const SerializationHelpers = {
|
|
|
28
28
|
kind: "function",
|
|
29
29
|
name: "serializeRecord",
|
|
30
30
|
location: "serialization/serialize-record.ts"
|
|
31
|
+
},
|
|
32
|
+
getBinaryResponse: {
|
|
33
|
+
kind: "function",
|
|
34
|
+
name: "getBinaryResponse",
|
|
35
|
+
location: "serialization/get-binary-response.ts"
|
|
31
36
|
}
|
|
32
37
|
} as const;
|
|
33
38
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HttpResponse, StreamableMethod } from "@azure-rest/core-client";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Gets a response type representing the given streamable response, using the stream methods
|
|
5
|
+
* to bypass Core's default response handling. This works around an issue where binary bodies in Core
|
|
6
|
+
* are coerced into UTF-8, regardless of whether the body is valid UTF-8 or not.
|
|
7
|
+
*/
|
|
8
|
+
export async function getBinaryResponse(streamableMethod: StreamableMethod): Promise<HttpResponse & { body?: Uint8Array }> {
|
|
9
|
+
const response = await streamableMethod.asBrowserStream();
|
|
10
|
+
|
|
11
|
+
if (response.body === undefined) {
|
|
12
|
+
return response as HttpResponse & { body?: Uint8Array };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const arrayBuffer = await new Response(response.body).arrayBuffer();
|
|
16
|
+
return {
|
|
17
|
+
...response,
|
|
18
|
+
body: new Uint8Array(arrayBuffer),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HttpResponse, StreamableMethod } from "@azure-rest/core-client";
|
|
2
|
+
import { Buffer } from "node:buffer";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Gets a response type representing the given streamable response, using the stream methods
|
|
6
|
+
* to bypass Core's default response handling. This works around an issue where binary bodies in Core
|
|
7
|
+
* are coerced into UTF-8, regardless of whether the body is valid UTF-8 or not.
|
|
8
|
+
*/
|
|
9
|
+
export async function getBinaryResponse(
|
|
10
|
+
streamableMethod: StreamableMethod
|
|
11
|
+
): Promise<HttpResponse & { body?: Uint8Array }> {
|
|
12
|
+
const response = await streamableMethod.asNodeStream();
|
|
13
|
+
if (response.body === undefined) {
|
|
14
|
+
return response as HttpResponse & { body?: Uint8Array };
|
|
15
|
+
}
|
|
16
|
+
const bufs: Buffer[] = [];
|
|
17
|
+
for await (const buf of response.body) {
|
|
18
|
+
bufs.push(Buffer.isBuffer(buf) ? buf : Buffer.from(buf));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
...response,
|
|
23
|
+
body: Buffer.concat(bufs)
|
|
24
|
+
};
|
|
25
|
+
}
|