-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adding support for generators with additional options
- Loading branch information
1 parent
0b6ce91
commit bf7ea54
Showing
5 changed files
with
236 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
|
||
const { Option, Command } = require("commander"); | ||
|
||
const generatorResolver = require("./generatorResolver"); | ||
|
||
const generatorOptionsPrefix = "generator."; | ||
|
||
async function generatorOptions(generatorPathOrUrl) { | ||
let optionsHelp = ""; | ||
const generatorPath = generatorResolver.getGenerator(generatorPathOrUrl); | ||
const configFile = path.join(generatorPath, "config.json"); | ||
|
||
if (!fs.existsSync(configFile)) { | ||
optionsHelp += "The generator has no additional options"; | ||
} else { | ||
const config = JSON.parse(fs.readFileSync(configFile, "utf8")); | ||
const options = configToCommanderOptions(config); | ||
|
||
// we use commander to create the formatted help for these options | ||
const command = new Command(); | ||
options.forEach((option) => command.addOption(option)); | ||
const commanderHelp = command.helpInformation(); | ||
|
||
// extract the parts we are interested in | ||
const lines = commanderHelp.split("\n"); | ||
lines.splice(0, 2); | ||
lines.splice(lines.length - 2, 2); | ||
|
||
optionsHelp += | ||
"This generator has a number of additional options which can be supplied when executing the 'forge' command.\n\n"; | ||
optionsHelp += lines.join("\n"); | ||
} | ||
|
||
generatorResolver.cleanup(); | ||
|
||
return optionsHelp; | ||
} | ||
|
||
// we use the commander library to parse the command line arguments and provide | ||
// help text. This function converts the config.json file into a set of options | ||
function configToCommanderOptions(config) { | ||
return Object.keys(config).map((optionName) => { | ||
const option = config[optionName]; | ||
const commanderOption = new Option(`--${generatorOptionsPrefix}${optionName} <value>`); | ||
if (option.description) { | ||
commanderOption.description = option.description; | ||
} | ||
if (option.choices) { | ||
commanderOption.choices(option.choices); | ||
commanderOption.default(option.choices[0]); | ||
} | ||
return commanderOption; | ||
}); | ||
} | ||
|
||
module.exports = { | ||
generatorOptions, | ||
configToCommanderOptions, | ||
generatorOptionsPrefix | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
const fs = require("fs"); | ||
|
||
const { generatorOptions } = require("../src/generatorOptions"); | ||
const generatorResolver = require("../src/generatorResolver"); | ||
|
||
jest.mock("fs"); | ||
jest.mock("../src/generatorResolver"); | ||
|
||
describe("generate", () => { | ||
beforeAll(() => { | ||
generatorResolver.getGenerator.mockImplementation((path) => path); | ||
}); | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
fs.existsSync.mockReturnValue(true); | ||
}); | ||
|
||
it("should indicate if the generator doesn't have any additional options", async () => { | ||
fs.existsSync.mockReturnValue(false); | ||
const optionsHelp = await generatorOptions("some/path"); | ||
expect(optionsHelp).toEqual("The generator has no additional options"); | ||
}); | ||
|
||
it("should include the description in the help output", async () => { | ||
const config = { | ||
moduleFormat: { | ||
description: "The module format to use for the generated code.", | ||
}, | ||
}; | ||
fs.readFileSync.mockReturnValue(JSON.stringify(config)); | ||
const optionsHelp = await generatorOptions("some/path"); | ||
expect(optionsHelp).toEqual( | ||
expect.stringMatching( | ||
/moduleFormat.*The module format to use for the generated code./ | ||
) | ||
); | ||
}); | ||
|
||
it("should treat the description as optional", async () => { | ||
const config = { | ||
moduleFormat: {}, | ||
}; | ||
fs.readFileSync.mockReturnValue(JSON.stringify(config)); | ||
const optionsHelp = await generatorOptions("some/path"); | ||
expect(optionsHelp).toEqual(expect.stringMatching(/moduleFormat/)); | ||
}); | ||
|
||
it("should handle multiple options", async () => { | ||
const config = { | ||
optionOne: { | ||
description: "description One.", | ||
}, | ||
optionTwo: { | ||
description: "description Two.", | ||
}, | ||
}; | ||
|
||
fs.readFileSync.mockReturnValue(JSON.stringify(config)); | ||
const optionsHelp = await generatorOptions("some/path"); | ||
|
||
expect(optionsHelp).toEqual( | ||
expect.stringMatching(/optionOne.*description One./) | ||
); | ||
expect(optionsHelp).toEqual( | ||
expect.stringMatching(/optionTwo.*description Two./) | ||
); | ||
}); | ||
|
||
it("should output choices", async () => { | ||
const config = { | ||
moduleFormat: { | ||
choices: ["cjs", "esm"], | ||
}, | ||
}; | ||
fs.readFileSync.mockReturnValue(JSON.stringify(config)); | ||
const optionsHelp = await generatorOptions("some/path"); | ||
expect(optionsHelp).toEqual( | ||
expect.stringMatching( | ||
/moduleFormat.*(choices: "cjs", "esm", default: "cjs")/ | ||
) | ||
); | ||
}); | ||
}); |