Skip to content

Commit d3359bc

Browse files
[tsp-client] Support generating a lock file from emitter-package.json (#7898)
* generate lock file from emitter-package.json * generate in eng dir
1 parent 05d74aa commit d3359bc

4 files changed

Lines changed: 66 additions & 33 deletions

File tree

tools/tsp-client/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ Convert an existing swagger specification to a TypeSpec project. This command sh
5050
--commit Commit to be used for project init or update [string]
5151
-d, --debug Enable debug logging [boolean]
5252
--emitter-options The options to pass to the emitter [string]
53+
--generate-lock-file Generate a lock file under the eng/ directory from
54+
an existing emitter-package.json [boolean]
5355
-h, --help Show help [boolean]
5456
--local-spec-repo Path to local repository with the TypeSpec project [string]
5557
--save-inputs Don't clean up the temp directory after generation [boolean]

tools/tsp-client/src/index.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,22 @@ async function convert(readme: string, outputDir: string, arm?: boolean): Promis
260260
return await npxCommand(outputDir, args);
261261
}
262262

263+
async function generateLockFile(rootUrl: string, repoRoot: string) {
264+
Logger.info("Generating lock file...");
265+
const args: string[] = ["install"];
266+
if (process.env['TSPCLIENT_FORCE_INSTALL']?.toLowerCase() === "true") {
267+
args.push("--force");
268+
}
269+
const tempRoot = await createTempDirectory(rootUrl);
270+
await cp(joinPaths(repoRoot, "eng", "emitter-package.json"), joinPaths(tempRoot, "package.json"));
271+
await npmCommand(tempRoot, args);
272+
const lockFile = await stat(joinPaths(tempRoot, "package-lock.json"));
273+
if (lockFile.isFile()) {
274+
await cp(joinPaths(tempRoot, "package-lock.json"), joinPaths(repoRoot, "eng", "emitter-package-lock.json"));
275+
}
276+
await removeDirectory(tempRoot);
277+
Logger.info(`Lock file generated in ${joinPaths(rootUrl, "emitter-package-lock.json")}`);
278+
}
263279

264280
async function main() {
265281
const options = await getOptions();
@@ -285,7 +301,12 @@ async function main() {
285301
} catch (err) {
286302
Logger.debug(`Error occurred while attempting to remove sparse-spec directory: ${err}`);
287303
}
288-
304+
305+
if (options.generateLockFile) {
306+
await generateLockFile(rootUrl, repoRoot);
307+
return;
308+
}
309+
289310
switch (options.command) {
290311
case "init":
291312
const emitter = await getEmitterFromRepoConfig(joinPaths(repoRoot, "eng", "emitter-package.json"));

tools/tsp-client/src/log.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ Options:
7575
--commit Commit to be used for project init or update [string]
7676
-d, --debug Enable debug logging [boolean]
7777
--emitter-options The options to pass to the emitter [string]
78+
--generate-lock-file Generate a lock file under the eng/ directory from
79+
an existing emitter-package.json [boolean]
7880
-h, --help Show help [boolean]
7981
--local-spec-repo Path to local repository with the TypeSpec project [string]
8082
--save-inputs Don't clean up the temp directory after generation [boolean]

tools/tsp-client/src/options.ts

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface Options {
1717
isUrl: boolean;
1818
localSpecRepo?: string;
1919
emitterOptions?: string;
20+
generateLockFile: boolean;
2021
swaggerReadme?: string;
2122
arm: boolean;
2223
}
@@ -54,6 +55,9 @@ export async function getOptions(): Promise<Options> {
5455
["emitter-options"]: {
5556
type: "string",
5657
},
58+
["generate-lock-file"]: {
59+
"type": "boolean",
60+
},
5761
["local-spec-repo"]: {
5862
type: "string",
5963
},
@@ -81,50 +85,53 @@ export async function getOptions(): Promise<Options> {
8185
process.exit(0);
8286
}
8387

84-
if (positionals.length === 0) {
85-
Logger.error("Command is required");
86-
printUsage();
87-
process.exit(1);
88-
}
88+
let isUrl = true;
8989
const supportedCommands = ["sync", "generate", "update", "init", "convert"];
90-
9190
const command = positionals[0];
92-
if (!command) {
93-
Logger.error("Command is required");
94-
printUsage();
95-
process.exit(1);
96-
}
9791

98-
if (!supportedCommands.includes(command)) {
99-
Logger.error(`Unknown command ${command}`);
100-
printUsage();
101-
process.exit(1);
102-
}
92+
if (!values["generate-lock-file"]) {
93+
if (positionals.length === 0) {
94+
Logger.error("Command is required");
95+
printUsage();
96+
process.exit(1);
97+
}
10398

104-
let isUrl = true;
105-
if (command === "init") {
106-
if (!values["tsp-config"]) {
107-
Logger.error("tspConfig is required");
99+
if (!command) {
100+
Logger.error("Command is required");
108101
printUsage();
109102
process.exit(1);
110103
}
111-
if (await doesFileExist(values["tsp-config"])) {
112-
isUrl = false;
104+
105+
if (!supportedCommands.includes(command)) {
106+
Logger.error(`Unknown command ${command}`);
107+
printUsage();
108+
process.exit(1);
113109
}
114-
if (!isUrl) {
115-
if (!values.commit || !values.repo) {
116-
Logger.error("The commit and repo options are required when tspConfig is a local directory");
110+
111+
if (command === "init") {
112+
if (!values["tsp-config"]) {
113+
Logger.error("tspConfig is required");
117114
printUsage();
118115
process.exit(1);
119116
}
117+
if (await doesFileExist(values["tsp-config"])) {
118+
isUrl = false;
119+
}
120+
if (!isUrl) {
121+
if (!values.commit || !values.repo) {
122+
Logger.error("The commit and repo options are required when tspConfig is a local directory");
123+
printUsage();
124+
process.exit(1);
125+
}
126+
}
120127
}
121-
}
122128

123-
if (command === "convert") {
124-
if (!values["swagger-readme"]) {
125-
Logger.error("Must specify a swagger readme with the `--swagger-readme` flag");
126-
printUsage();
127-
process.exit(1);
129+
if (command === "convert") {
130+
if (!values["swagger-readme"]) {
131+
Logger.error("Must specify a swagger readme with the `--swagger-readme` flag");
132+
printUsage();
133+
process.exit(1);
134+
}
128135
}
129136
}
130137

@@ -158,7 +165,7 @@ export async function getOptions(): Promise<Options> {
158165

159166
return {
160167
debug: values.debug ?? false,
161-
command: command,
168+
command: command ?? "",
162169
tspConfig: values["tsp-config"],
163170
noCleanup: values["save-inputs"] ?? false,
164171
skipSyncAndGenerate: values["skip-sync-and-generate"] ?? false,
@@ -168,6 +175,7 @@ export async function getOptions(): Promise<Options> {
168175
isUrl: isUrl,
169176
localSpecRepo: values["local-spec-repo"],
170177
emitterOptions: values["emitter-options"],
178+
generateLockFile: values["generate-lock-file"] ?? false,
171179
swaggerReadme: values["swagger-readme"],
172180
arm: values.arm ?? false,
173181
};

0 commit comments

Comments
 (0)