Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support to pull templates from private npm repository #877

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions lib/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const DEFAULT_TEMPLATES_DIR = path.resolve(ROOT_DIR, 'node_modules');

const TRANSPILED_TEMPLATE_LOCATION = '__transpiled';
const TEMPLATE_CONTENT_DIRNAME = 'template';
const GENERATOR_OPTIONS = ['debug', 'disabledHooks', 'entrypoint', 'forceWrite', 'install', 'noOverwriteGlobs', 'output', 'templateParams', 'mapBaseUrlToFolder'];
const GENERATOR_OPTIONS = ['debug', 'disabledHooks', 'entrypoint', 'forceWrite', 'install', 'noOverwriteGlobs', 'output', 'templateParams', 'mapBaseUrlToFolder','registry','registryUsername','registryPassword','registryToken'];

const logMessage = require('./logMessages');

Expand Down Expand Up @@ -91,8 +91,12 @@ class Generator {
* @param {Boolean} [options.install=false] Install the template and its dependencies, even when the template has already been installed.
* @param {Boolean} [options.debug=false] Enable more specific errors in the console. At the moment it only shows specific errors about filters. Keep in mind that as a result errors about template are less descriptive.
* @param {Object<String, String>} [options.mapBaseUrlToFolder] Optional parameter to map schema references from a base url to a local base folder e.g. url=https://schema.example.com/crm/ folder=./test/docs/ .
* @param {String} [options.registry] Optional parameter to pass npm registry url
* @param {String} [options.registryUsername] Optional parameter to pass npm registry username
* @param {String} [options.registryPassword] Optional parameter to pass npm registry base64 encoded password
* @param {String} [options.registryToken] Optional parameter to pass npm registry auth token
*/
constructor(templateName, targetDir, { templateParams = {}, entrypoint, noOverwriteGlobs, disabledHooks, output = 'fs', forceWrite = false, install = false, debug = false, mapBaseUrlToFolder = {} } = {}) {
constructor(templateName, targetDir, { templateParams = {}, entrypoint, noOverwriteGlobs, disabledHooks, output = 'fs', forceWrite = false, install = false, debug = false, mapBaseUrlToFolder = {}, registry, registryUsername, registryPassword, registryToken } = {}) {
const invalidOptions = getInvalidOptions(GENERATOR_OPTIONS, arguments[arguments.length - 1] || []);
if (invalidOptions.length) throw new Error(`These options are not supported by the generator: ${invalidOptions.join(', ')}`);
if (!templateName) throw new Error('No template name has been specified.');
Expand Down Expand Up @@ -123,6 +127,14 @@ class Generator {
this.hooks = {};
/** @type {Object} Maps schema URL to folder. */
this.mapBaseUrlToFolder = mapBaseUrlToFolder;
/** @type {String} Npm registry url. */
this.registry = registry;
/** @type {String} Npm registry username. */
this.registryUsername = registryUsername;
/** @type {String} Npm registry base64 encoded password. */
this.registryPassword = registryPassword;
/** @type {String} Npm registry token. */
this.registryToken = registryToken;

// Load template configuration
/** @type {Object} The template parameters. The structure for this object is based on each individual template. */
Expand Down Expand Up @@ -385,9 +397,22 @@ class Generator {

if (isFileSystemPath(this.templateName)) log.debug(logMessage.NPM_INSTALL_TRIGGER);

const arb = new Arborist({
path: ROOT_DIR
});
const arbOptions = {
path: ROOT_DIR,
};
if (this.registry) {
arbOptions.registry = this.registry;
}
if (this.registryUsername) {
arbOptions.username = this.registryUsername;
}
if (this.registryPassword) {
arbOptions.password = this.registryPassword;
}
if (this.registryToken) {
arbOptions.token = this.registryToken;
}
const arb = new Arborist(arbOptions);

try {
const installResult = await arb.reify({
Expand Down
12 changes: 11 additions & 1 deletion test/generator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ describe('Generator', () => {
const utils = require('../lib/utils');
const asyncapiURL = 'http://example.com/fake-asyncapi.yml';
utils.__contentOfFetchedFile = 'fake text';

const generateFromStringMock = jest.fn().mockResolvedValue();
const gen = new Generator('testTemplate', __dirname);
gen.generateFromString = generateFromStringMock;
Expand Down Expand Up @@ -410,6 +410,16 @@ describe('Generator', () => {
}, 0);
});

it('works with a path to registry', async () => {
log.debug = jest.fn();
utils.__getTemplateDetails = undefined;
const gen = new Generator('nameOfTestTemplate', __dirname, {debug: true, registry: 'some.registry.com', registryUsername: 'user', registryPassword: 'password', registryToken: 'token'});
await gen.installTemplate();
setTimeout(() => { // This puts the call at the end of the Node.js event loop queue.
expect(arboristMock.reify).toHaveBeenCalledTimes(1);
}, 0);
});

it('works with a url and force = true', async () => {
const gen = new Generator('https://my-test-template.com', __dirname);
await gen.installTemplate(true);
Expand Down