Skip to content

Commit

Permalink
feat!: template pulling with npm config (#1069)
Browse files Browse the repository at this point in the history
Co-authored-by: Lukasz Gornicki <[email protected]>%0ACo-authored-by: Pierrick BOULÉ <[email protected]>
  • Loading branch information
pierrick-boule and Lukasz Gornicki <[email protected]>%0ACo-authored-by: Pierrick BOULÉ authored Apr 24, 2024
1 parent f74419c commit 63f8b58
Show file tree
Hide file tree
Showing 11 changed files with 1,000 additions and 71 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pr-testing-with-test-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: [ '12', '14', '16', '18' ]
node: [ '18', '20' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
Expand Down
4 changes: 2 additions & 2 deletions docs/installation-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ You can use the generator library to generate whatever you want in your event-dr

## Prerequisites
Before you install and use the AsyncAPI CLI and the generator library, ensure you meet the prerequisites below, then [install the CLI](#installation).
1. Node.js v12.16 and higher
2. Npm v6.13.7 and higher
1. Node.js v18.12.0 and higher
2. Npm v8.19.0 and higher

To verify the versions of Node and Npm you have, run the following command on your terminal:
```
Expand Down
20 changes: 16 additions & 4 deletions docs/using-private-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,26 @@
title: "Using private templates"
weight: 180
---
Generator allows fetching the template from private repositories like Verdaccio, Nexus, npm, etc.
Generator allows fetching the template from private repositories like Verdaccio, Nexus, npm, etc.
By default, the generator fetches the template from the public npm registry configured in the npm configuration.
To fetch the template from a private registry, you need to provide the registry URL and authentication details in the .npmrc. For more information [read the docs](https://docs.npmjs.com/cli/v9/configuring-npm/npmrc).
However, you can override the default behavior by providing the registry URL and authentication details as arguments of the commandline.


## Private registry options:
## Private registry using .npmrc:
```bash
npm config set registry http://verdaccio:4873
npm config set //verdaccio:4873/:_auth=$(echo -n 'username:password' | base64)
```
* **npm config set registry** : Provide the registry URL that points to the registry URL.
* **npm config set _auth** : Provide the base64 encoded value that represents the username and password for basic auth.
* **npm config set _authToken** : Provide the access token generated by the registry.

## Private registry overriding arguments:

* **registry.url**: The URL of the registry where the private template is located. Defaults to `registry.npmjs.org`.
* **registry.auth**: An optional parameter to pass the npm registry username and password encoded with base64, formatted as `username:password`. For example, if the username and password are `admin` and `nimda`, you need to encode them with the base64 value like `admin:nimda` which results in `YWRtaW46bmltZGE=`.
**registry.token**: An optional parameter to pass to the npm registry authentication token. To get the token, you can first authenticate with the registry using `npm login` and then grab the generated token from the `.npmrc` file.
* **registry.token**: An optional parameter to pass to the npm registry authentication token. To get the token, you can first authenticate with the registry using `npm login` and then grab the generated token from the `.npmrc` file.

## Pulling private template using library:

Expand All @@ -26,4 +38,4 @@ const generator = new Generator('@asyncapi/html-template', 'output',
}
});
```
Assuming you host `@asyncapi/html-template` in a private package registry like Verdaccio. To pull this template, you need to provide `registry.url` option that points to the registry URL and `registry.auth` as a base64 encoded value that represents the username and password. Instead of username and password, you can also pass `registry.token`.
Assuming you host `@asyncapi/html-template` in a private package registry like Verdaccio. To pull this template, you need to provide `registry.url` option that points to the registry URL and `registry.auth` as a base64 encoded value that represents the username and password. Instead of username and password, you can also pass `registry.token`.
47 changes: 30 additions & 17 deletions lib/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ const filenamify = require('filenamify');
const git = require('simple-git');
const log = require('loglevel');
const Arborist = require('@npmcli/arborist');
const Config = require('@npmcli/config');
const requireg = require('requireg');
const npmPath = requireg.resolve('npm').replace('index.js','');

const { isAsyncAPIDocument } = require('@asyncapi/parser/cjs/document');

const { configureReact, renderReact, saveRenderedReactContent } = require('./renderer/react');
Expand All @@ -31,6 +35,7 @@ const {
const { parse, usesNewAPI, getProperApiDocument } = require('./parser');
const { registerFilters } = require('./filtersRegistry');
const { registerHooks } = require('./hooksRegistry');
const { definitions, flatten, shorthands } = require('@npmcli/config/lib/definitions');

const FILTERS_DIRNAME = 'filters';
const HOOKS_DIRNAME = 'hooks';
Expand Down Expand Up @@ -532,7 +537,7 @@ class Generator {
arbOptions.registry = providedRegistry;
registryUrl = providedRegistry;
}

const domainName = registryUrl.replace(/^https?:\/\//, '');
//doing basic if/else so basically only one auth type is used and token as more secure is primary
if (this.registry.token) {
Expand All @@ -541,11 +546,12 @@ class Generator {
} else if (this.registry.auth) {
authorizationName = `//${domainName}:_auth`;
arbOptions[authorizationName] = this.registry.auth;
}
}

//not sharing in logs neither token nor auth for security reasons
log.debug(`Using npm registry ${registryUrl} and authorization type ${authorizationName} to handle template installation.`);
}

/**
* Downloads and installs a template and its dependencies
*
Expand All @@ -556,14 +562,14 @@ class Generator {
let pkgPath;
let installedPkg;
let packageVersion;

try {
installedPkg = getTemplateDetails(this.templateName, PACKAGE_JSON_FILENAME);
pkgPath = installedPkg && installedPkg.pkgPath;
packageVersion = installedPkg && installedPkg.version;
log.debug(logMessage.templateSource(pkgPath));
if (packageVersion) log.debug(logMessage.templateVersion(packageVersion));

return {
name: installedPkg.name,
path: pkgPath
Expand All @@ -573,38 +579,45 @@ class Generator {
// We did our best. Proceed with installation...
}
}

const debugMessage = force ? logMessage.TEMPLATE_INSTALL_FLAG_MSG : logMessage.TEMPLATE_INSTALL_DISK_MSG;
log.debug(logMessage.installationDebugMessage(debugMessage));

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

const arbOptions = {
path: ROOT_DIR,
};
if (this.registry) {

const config = new Config({
definitions,
flatten,
shorthands,
npmPath
});

await config.load();

const arbOptions = {...{path: ROOT_DIR}, ...config.flat};

if (Object.keys(this.registry).length !== 0) {
this.initialiseArbOptions(arbOptions);
}

const arb = new Arborist(arbOptions);

try {
const installResult = await arb.reify({
add: [this.templateName],
saveType: 'prod',
save: false
});

const addResult = arb[Symbol.for('resolvedAdd')];
if (!addResult) throw new Error('Unable to resolve the name of the added package. It was most probably not added to node_modules successfully');

const packageName = addResult[0].name;
const packageVersion = installResult.children.get(packageName).version;
const packagePath = installResult.children.get(packageName).path;

if (!isFileSystemPath(this.templateName)) log.debug(logMessage.templateSuccessfullyInstalled(packageName, packagePath));
if (packageVersion) log.debug(logMessage.templateVersion(packageVersion));

return {
name: packageName,
path: packagePath,
Expand Down
Loading

0 comments on commit 63f8b58

Please sign in to comment.