Skip to content

Commit 0592536

Browse files
xirzecCopilot
andauthored
Audit and trim @azure-tools/typespec-ts emitter dependencies (#4754)
Fixes #4537. This PR audits the `@azure-tools/typespec-ts` emitter's dependencies and removes/replaces several that were unmaintained, redundant, or only powering dead code paths. ## Dependency changes - **Removed `handlebars`** (runtime dep) — replaced the four metadata builders with a tiny in-house `renderTemplate` (a mustache subset supporting `{{var}}` and `{{#if}}/{{else}}/{{/if}}` with handlebars standalone-whitespace semantics). Output was verified byte-identical against handlebars across a boolean matrix. - **Removed `mkdirp`** (devDep) — the only usage (`mkdirp -p coverage`) is now a portable `node -e "require('fs').mkdirSync('coverage',{recursive:true})"`. - **Removed redundant `prettier`** from `devDependencies` (it was already in `dependencies`). - **Replaced unmaintained `npm-run-all`** with `concurrently` (already in the repo catalog, actively maintained). `npm-run-all` had no release since 2018. Mapped `--race` to `concurrently --kill-others --success first` and verified the exit-code/teardown semantics. - Dropped `handlebars`, `mkdirp`, and `npm-run-all` from the workspace catalog. ## Cleanup enabled by the audit - **Removed dead README template paths**: `karmaConfig`, `nonBrandedReadmeTemplate`, and `serviceDocURL` were unused; the README template now treats the `@azure` scope as always-on (every generated package is branded), dropping the `{{#if azure}}` gates. - **Removed the internal `is-typespec-test` emitter option** — its only effect was gating the README "Install the package" section. Cleaned up the option schema, interface, transform, docs, regenerated reference docs, and 79 test `tspconfig.yaml` fixtures. ## Merge - Merged latest `main` (including #4750's coverage/spector unification); resolved the one `package.json` scripts conflict. ## Verification Replicated the `Consistency` CI gates locally: `format:check`, package `lint`, `cspell`, `chronus verify`, and `deps check` (catalog-sync) all pass. Build, `test-next`, and `unit-test` suites are green. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8d517e0 commit 0592536

98 files changed

Lines changed: 345 additions & 541 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: internal
3+
packages:
4+
- "@azure-tools/typespec-ts"
5+
---
6+
7+
Remove unused `handlebars` and `mkdirp` dependencies. README, snippets, sample-test, and recorded-client metadata files now use a small built-in template renderer instead of Handlebars, and the test-server scripts create the coverage directory with Node instead of `mkdirp`. Also drop dead metadata templates (`karmaConfig`, the non-branded README template) that were no longer emitted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: internal
3+
packages:
4+
- "@azure-tools/typespec-ts"
5+
---
6+
7+
Remove the internal `is-typespec-test` emitter option. Its only effect was hiding the README "Install the package" section for test packages, so the install section is now always emitted and the option (and the `isReleasablePackage` metadata it gated) has been dropped.

packages/typespec-ts/CONTRIBUTING.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ pnpm check:tree # fails if regeneration left the git tree dirty
8484
emitter-output-dir: "{project-root}"
8585
generate-metadata: true
8686
generate-test: false
87-
is-typespec-test: true
8887
hierarchy-client: false
8988
package-details:
9089
name: "@msinternal/auth-apikey"

packages/typespec-ts/README.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,6 @@ other cases:
126126

127127
Whether to generate sample files, for basic samples of your generated sdks. Defaults to `undefined`. Management packages' default to `true`.
128128

129-
### `is-typespec-test`
130-
131-
**Type:** `boolean`
132-
133-
Internal option for test
134-
135129
### `azure-arm`
136130

137131
**Type:** `boolean`

packages/typespec-ts/package.json

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
"lint": "eslint . --ext .ts --max-warnings=0",
2424
"lint:fix": "eslint . --fix --ext .ts",
2525
"check:tree": "node ./test/commands/check-clean-tree.ts",
26-
"integration-test-ci": "npm-run-all copy:typespec spector-test",
27-
"spector-test": "npm-run-all --silent -p start-test-server --race generate-and-run",
28-
"start-test-server": "mkdirp -p coverage && npx tsp-spector serve ./node_modules/@azure-tools/azure-http-specs/specs ./node_modules/@typespec/http-specs/specs --port 3002 --coverageFile ./coverage/spector-coverage-typescript-azure.json",
26+
"integration-test-ci": "npm run copy:typespec && npm run spector-test",
27+
"spector-test": "concurrently --kill-others --success first \"npm:start-test-server\" \"npm:generate-and-run\"",
28+
"start-test-server": "node ./test/commands/start-test-server.js",
2929
"copy:typespec": "node ./test/commands/copy-typespec.ts",
30-
"generate-and-run": "npm run generate-tsp-only:client && npm-run-all -p integration-test:alone generate-tsp-only:declarations && npm run stop-test-server -- -p 3002",
30+
"generate-and-run": "npm run generate-tsp-only:client && concurrently --kill-others-on-fail \"npm:integration-test:alone\" \"npm:generate-tsp-only:declarations\" && npm run stop-test-server -- -p 3002",
3131
"generate-tsp-only": "node ./test/commands/gen-spector.js",
3232
"generate-tsp-only:client": "node ./test/commands/gen-spector.js --phase=client",
3333
"generate-tsp-only:declarations": "node ./test/commands/gen-spector.js --phase=declarations",
@@ -66,9 +66,7 @@
6666
"@typespec/xml": "workspace:^",
6767
"@typespec/ts-http-runtime": "catalog:",
6868
"cross-env": "catalog:",
69-
"mkdirp": "catalog:",
70-
"npm-run-all": "catalog:",
71-
"prettier": "catalog:",
69+
"concurrently": "catalog:",
7270
"vitest": "catalog:",
7371
"vite": "catalog:",
7472
"@vitest/coverage-v8": "catalog:",
@@ -86,7 +84,6 @@
8684
},
8785
"dependencies": {
8886
"fast-xml-parser": "catalog:",
89-
"handlebars": "catalog:",
9087
"prettier": "catalog:",
9188
"ts-morph": "catalog:",
9289
"tslib": "catalog:"

packages/typespec-ts/src/interfaces.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,6 @@ export interface ClientOptions {
223223
generateTest?: boolean;
224224
generateSample?: boolean;
225225
azureOutputDirectory?: string;
226-
isTypeSpecTest?: boolean;
227226
serviceInfo?: ServiceInfo;
228227
azureArm?: boolean;
229228
enableOperationGroup?: boolean;

packages/typespec-ts/src/lib.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export interface EmitterOptions {
3939
*/
4040
"generate-test"?: boolean;
4141
"generate-sample"?: boolean;
42-
"is-typespec-test"?: boolean;
4342
"azure-arm"?: boolean;
4443
"enable-operation-group"?: boolean;
4544
"enable-model-namespace"?: boolean;
@@ -170,11 +169,6 @@ export const EmitterOptionsSchema: JSONSchemaType<EmitterOptions> = {
170169
description:
171170
"Whether to generate sample files, for basic samples of your generated sdks. Defaults to `undefined`. Management packages' default to `true`.",
172171
},
173-
"is-typespec-test": {
174-
type: "boolean",
175-
nullable: true,
176-
description: "Internal option for test",
177-
},
178172
"azure-arm": {
179173
type: "boolean",
180174
nullable: true,

packages/typespec-ts/src/metadata/build-readme-file.ts

Lines changed: 17 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
33

4-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
5-
// @ts-ignore: to fix the handlebars issue
6-
import hbs from "handlebars";
74
import { ClientModel } from "../interfaces.js";
85
import { getClientName } from "../utils/name-constructors.js";
96
import { NameType, normalizeName } from "../utils/name-utils.js";
7+
import { renderTemplate } from "./render-template.js";
108

119
const azureReadmeModularTemplate = `# {{ clientDescriptiveName }} library for JavaScript
1210
@@ -38,23 +36,18 @@ Key links:
3836
3937
See our [support policy](https://github.com/Azure/azure-sdk-for-js/blob/main/SUPPORT.md) for more details.
4038
41-
{{#if azure}}
4239
### Prerequisites
4340
4441
- An [Azure subscription][azure_sub].
45-
{{/if}}
4642
47-
{{#if isReleasablePackage}}
4843
### Install the \`{{ clientPackageName }}\` package
4944
5045
Install the {{ clientDescriptiveName }} library for JavaScript with \`npm\`:
5146
5247
\`\`\`bash
5348
npm install {{ clientPackageName }}
5449
\`\`\`
55-
{{/if}}
5650
57-
{{#if azure}}
5851
{{#if addCredentials}}
5952
### Create and authenticate a \`{{ clientClassName}}\`
6053
@@ -129,7 +122,8 @@ const credential = new InteractiveBrowserCredential({
129122
const client = new {{ clientClassName }}("<endpoint>", credential);
130123
\`\`\`
131124
{{/if}}
132-
{{/if}}{{/if}}
125+
{{/if}}
126+
133127
134128
### JavaScript Bundle
135129
To use this client library in the browser, first you need to use a bundler. For details on how to do this, please refer to our [bundling documentation](https://aka.ms/AzureSDKBundling).
@@ -140,7 +134,6 @@ To use this client library in the browser, first you need to use a bundler. For
140134
141135
\`{{ clientClassName }}\` is the primary interface for developers using the {{ clientDescriptiveName }} library. Explore the methods on this client object to understand the different features of the {{ serviceName }} service that you can access.
142136
143-
{{#if azure}}
144137
## Troubleshooting
145138
146139
### Logging
@@ -153,7 +146,7 @@ import { setLogLevel } from "@azure/logger";
153146
setLogLevel("info");
154147
\`\`\`
155148
156-
For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs]({{ repoURL }}/tree/main/sdk/core/logger).
149+
For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger).
157150
158151
{{#if samplesURL}}
159152
## Next steps
@@ -163,54 +156,16 @@ Please take a look at the [samples]({{ samplesURL }}) directory for detailed exa
163156
164157
## Contributing
165158
166-
If you'd like to contribute to this library, please read the [contributing guide]({{ contributingGuideURL }}) to learn more about how to build and test the code.
159+
If you'd like to contribute to this library, please read the [contributing guide](https://github.com/Azure/azure-sdk-for-js/blob/main/CONTRIBUTING.md) to learn more about how to build and test the code.
167160
168161
## Related projects
169162
170-
- [{{ projectName }}]({{ repoURL }})
163+
- [Microsoft Azure SDK for JavaScript](https://github.com/Azure/azure-sdk-for-js)
171164
172165
[azure_sub]: https://azure.microsoft.com/free/
173166
[azure_portal]: https://portal.azure.com
174-
{{#if identityPackageURL}}[azure_identity]: {{ identityPackageURL }}
175-
{{/if}}[defaultazurecredential]: {{ identityPackageURL }}#defaultazurecredential
176-
{{/if}}
177-
`;
178-
179-
const nonBrandedReadmeTemplate = `# {{ clientDescriptiveName }} library for JavaScript
180-
181-
{{ description }}
182-
183-
Key links:
184-
185-
{{#if packageSourceURL}}
186-
- [Source code]({{ packageSourceURL }})
187-
{{/if}}
188-
{{#if packageNPMURL}}
189-
- [Package (NPM)]({{ packageNPMURL }})
190-
{{/if}}
191-
{{#if apiRefURL}}
192-
- [API reference documentation]({{ apiRefURL }})
193-
{{/if}}
194-
{{#if serviceDocURL}}
195-
- [Product documentation]({{ serviceDocURL }})
196-
{{/if}}
197-
{{#if samplesURL}}
198-
- [Samples]({{ samplesURL }})
199-
{{/if}}
200-
201-
## Getting started
202-
203-
### Currently supported environments
204-
205-
- LTS versions of Node.js
206-
207-
### Install the \`{{ clientPackageName }}\` package
208-
209-
Install the {{ clientDescriptiveName }} library for JavaScript with \`npm\`:
210-
211-
\`\`\`bash
212-
npm install {{ clientPackageName }}
213-
\`\`\`
167+
[azure_identity]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity
168+
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/identity/identity#defaultazurecredential
214169
`;
215170

216171
const apiReferenceTemplate = `{{#if apiRefURL}}
@@ -228,8 +183,6 @@ interface Metadata {
228183
clientPackageName: string;
229184
/** The name of the client class */
230185
clientClassName: string;
231-
/** The URL of the repository the package lives in */
232-
repoURL?: string;
233186
/** The URL to the package directory in the repository */
234187
packageSourceURL?: string;
235188
/** The URL to the package's samples */
@@ -240,29 +193,12 @@ interface Metadata {
240193
description?: string;
241194
/** The URL to the package on npmjs.org */
242195
packageNPMURL?: string;
243-
/** The name of the project that lives in the repository */
244-
projectName?: string;
245196
/** whether the client accepts standard credentials */
246197
addCredentials?: boolean;
247-
/** The link to the identity package in the repository */
248-
identityPackageURL?: string;
249-
/** The URL for the service document */
250-
serviceDocURL?: string;
251-
/** The dependency info for this service */
252-
dependencyDescription?: string;
253-
dependencyLink?: string;
254-
/** Indicates if the package is a multi-client */
255-
hasMultiClients?: boolean;
256198
/** The URL to the API reference */
257199
apiRefURL?: string;
258200
/** Check if the rp is management plane */
259201
azureArm?: boolean;
260-
/** Whether the package being generated is for an Azure service */
261-
azure: boolean;
262-
/** Indicates if the package is a test/releasable package. */
263-
isReleasablePackage?: boolean;
264-
/** The link to the contributing guide in the repository */
265-
contributingGuideURL?: string;
266202
/** Indicates if the package need generate test files */
267203
generateTest?: boolean;
268204
/** Indicates if the package need SubscriptionId as the client parameter */
@@ -271,13 +207,10 @@ interface Metadata {
271207

272208
export function buildReadmeFile(model: ClientModel) {
273209
const metadata = createMetadata(model) ?? {};
274-
const readmeFileContents = hbs.compile(
275-
model.options ? azureReadmeModularTemplate : nonBrandedReadmeTemplate,
276-
{ noEscape: true },
277-
);
210+
const content = renderTemplate(azureReadmeModularTemplate, metadata as Record<string, unknown>);
278211
return {
279212
path: "README.md",
280-
content: readmeFileContents(metadata),
213+
content,
281214
};
282215
}
283216

@@ -301,7 +234,10 @@ export function updateReadmeFile(
301234
try {
302235
const metadata = createMetadata(model) ?? {};
303236

304-
const newApiRefLink = hbs.compile(apiReferenceTemplate, { noEscape: true })(metadata).trim();
237+
const newApiRefLink = renderTemplate(
238+
apiReferenceTemplate,
239+
metadata as Record<string, unknown>,
240+
).trim();
305241

306242
if (!newApiRefLink) {
307243
return { path: "README.md", content: existingReadmeContent };
@@ -329,14 +265,12 @@ function createMetadata(model: ClientModel): Metadata | undefined {
329265
return;
330266
}
331267
// const packageDetails = model.options.packageDetails;
332-
const { packageDetails, azureOutputDirectory, serviceInfo, isTypeSpecTest } = model.options;
268+
const { packageDetails, azureOutputDirectory, serviceInfo } = model.options;
333269

334-
const azureHuh =
335-
packageDetails?.scopeName === "azure" || packageDetails?.scopeName === "azure-rest";
336270
const repoURL = "https://github.com/Azure/azure-sdk-for-js";
337271
const relativePackageSourcePath = azureOutputDirectory;
338272
const packageSourceURL =
339-
relativePackageSourcePath && repoURL && `${repoURL}/tree/main/${relativePackageSourcePath}`;
273+
relativePackageSourcePath && `${repoURL}/tree/main/${relativePackageSourcePath}`;
340274

341275
const clientPackageName = packageDetails?.name;
342276
const clientClassName = getClientName(model);
@@ -363,17 +297,9 @@ function createMetadata(model: ClientModel): Metadata | undefined {
363297
packageNPMURL: `https://www.npmjs.com/package/${clientPackageName}`,
364298
samplesURL:
365299
model.options.generateSample && packageSourceURL ? `${packageSourceURL}/samples` : undefined,
366-
apiRefURL: azureHuh
367-
? `https://learn.microsoft.com/javascript/api/${clientPackageName}${apiRefUrlQueryParameter}`
368-
: undefined,
300+
apiRefURL: `https://learn.microsoft.com/javascript/api/${clientPackageName}${apiRefUrlQueryParameter}`,
369301
azureArm: Boolean(model.options.azureArm),
370-
azure: azureHuh,
371-
isReleasablePackage: !isTypeSpecTest,
372-
repoURL: repoURL,
373-
projectName: azureHuh ? "Microsoft Azure SDK for JavaScript" : undefined,
374-
identityPackageURL: repoURL && `${repoURL}/tree/main/sdk/identity/identity`,
375302
addCredentials: model.options.addCredentials,
376-
contributingGuideURL: repoURL && `${repoURL}/blob/main/CONTRIBUTING.md`,
377303
generateTest: model.options.generateTest,
378304
hasSubscriptionId: model.options.hasSubscriptionId,
379305
};

0 commit comments

Comments
 (0)