AWS DevOps & Developer Productivity Blog
Publishing private npm packages with AWS CodeArtifact
This post demonstrates how to create, publish, and download private npm packages using AWS CodeArtifact, allowing you to share code across your organization without exposing your packages to the public.
The ability to control CodeArtifact repository access using AWS Identity and Access Management (IAM) removes the need to manage additional credentials for a private npm repository when developers already have IAM roles configured.
You can use private npm packages for a variety of use cases, such as:
- Reducing code duplication
- Configuration such as code linting and styling
- CLI tools for internal processes
This post shows how to easily create a sample project in which we publish an npm package and install the package from CodeArtifact. For more information about pipeline integration, see AWS CodeArtifact and your package management flow – Best Practices for Integration.
Solution overview
The following diagram illustrates this solution.
In this post, you create a private scoped npm package containing a sample function that can be used across your organization. You create a second project to download the npm package. You also learn how to structure your npm package to make logging in to CodeArtifact automatic when you want to build or publish the package.
The code covered in this post is available on GitHub:
- aws-codeartifact-npm-example – Sample npm package and application
Prerequisites
Update (06/25/2021): The following solution is intended for use with npm v6 and earlier.
Before you begin, you need to complete the following:
- Create an AWS account.
- Install the AWS Command Line Interface (AWS CLI). CodeArtifact is supported in these CLI versions:
- 1.18.83 or later: install the AWS CLI version 1
- 2.0.54 or later: install the AWS CLI version 2
- Run
npm --version
to make sure you’re running npm v6 or earlier. - Create a CodeArtifact repository.
- Add required IAM permissions for CodeArtifact.
Creating your npm package
You can create your npm package in three easy steps: set up the project, create your npm script for authenticating with CodeArtifact, and publish the package.
Setting up your project
Create a directory for your new npm package. We name this directory my-package
because it serves as the name of the package. We use an npm scope for this package, where @myorg
represents the scope all of our organization’s packages are published under. This helps us distinguish our internal private package from external packages. See the following code:
npm init --scope=@myorg -y
{
"name": "@myorg/my-package",
"version": "1.0.0",
"description": "A sample private scoped npm package",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}
The package.json file specifies that the main
file of the package is called index.js
. Next, we create that file and add our package function to it:
module.exports.helloWorld = function() {
console.log('Hello world!');
}
Creating an npm script
To create your npm script, complete the following steps:
- On the CodeArtifact console, choose the repository you created as part of the prerequisites.
If you haven’t created a repository, create one before proceeding.
- Select your CodeArtifact repository and choose Details to view the additional details for your repository.
We use two items from this page:
- Repository name (
my-repo
) - Domain (
my-domain
)
- Create a script named
co:login
in our package.json. The package.json contains the following code:
{
"name": "@myorg/my-package",
"version": "1.0.0",
"description": "A sample private scoped npm package",
"main": "index.js",
"scripts": {
"co:login": "aws codeartifact login --tool npm --repository my-repo --domain my-domain",
"test": "echo \"Error: no test specified\" && exit 1"
}
}
Running this script updates your npm configuration to use your CodeArtifact repository and sets your authentication token, which expires after 12 hours.
- To test our new script, enter the following command:
npm run co:login
The following code is the output:
> aws codeartifact login --tool npm --repository my-repo --domain my-domain
Successfully configured npm to use AWS CodeArtifact repository https://my-domain-<ACCOUNT ID>.d.codeartifact.us-east-1.amazonaws.com/npm/my-repo/
Login expires in 12 hours at 2020-09-04 02:16:17-04:00
- Add a
prepare
script to our package.json to run our login command:
{
"name": "@myorg/my-package",
"version": "1.0.0",
"description": "A sample private scoped npm package",
"main": "index.js",
"scripts": {
"prepare": "npm run co:login",
"co:login": "aws codeartifact login --tool npm --repository my-repo --domain my-domain",
"test": "echo \"Error: no test specified\" && exit 1"
}
}
This configures our project to automatically authenticate and generate an access token anytime npm install
or npm publish
run on the project.
If you see an error containing Invalid choice, valid choices are:
, you need to update the AWS CLI according to the versions listed in the prerequisites of this post.
Publishing your package
To publish our new package for the first time, run npm publish
.
The following screenshot shows the output.
If we navigate to our CodeArtifact repository on the CodeArtifact console, we now see our new private npm package ready to be downloaded.
Installing your private npm package
To install your private npm package, you first set up the project and add the CodeArtifact configs. After you install your package, it’s ready to use.
Setting up your project
Create a directory for a new application and name it my-app. This is a sample project to download our private npm package published in the previous step. You can apply this pattern to all repositories you intend on installing your organization’s npm packages in.
npm init -y
{
"name": "my-app",
"version": "1.0.0",
"description": "A sample application consuming a private scoped npm package",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}
Adding CodeArtifact configs
Add the npm scripts preinstall
and co:login
, similar to what was created earlier to your new project:
{
"name": "my-app",
"version": "1.0.0",
"description": "A sample application consuming a private scoped npm package",
"main": "index.js",
"scripts": {
"preinstall": "npm run co:login",
"co:login": "aws codeartifact login --tool npm --repository my-repo --domain my-domain",
"test": "echo \"Error: no test specified\" && exit 1"
}
}
Installing your new private npm package
Enter the following command:
npm install @myorg/my-package
Your package.json should now list @myorg/my-package
in your dependencies:
{
"name": "my-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"preinstall": "npm run co:login",
"co:login": "aws codeartifact login --tool npm --repository my-repo --domain my-domain",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@myorg/my-package": "^1.0.0"
}
}
Using your new npm package
In our my-app application, create a file named index.js to run code from our package containing the following:
const { helloWorld } = require('@myorg/my-package');
helloWorld();
Run node index.js
in your terminal to see the console print the message from our @myorg/my-package
helloWorld
function.
Cleaning Up
If you created a CodeArtifact repository for the purposes of this post, use one of the following methods to delete the repository:
Remove the changes made to your user profile’s npm configuration by running npm config delete registry
, this will remove the CodeArtifact repository from being set as your default npm registry.
Conclusion
In this post, you successfully published a private scoped npm package stored in CodeArtifact, which you can reuse across multiple teams and projects within your organization. You can use npm scripts to streamline the authentication process and apply this pattern to save time.
About the Author
Ryan Sonshine is a Cloud Application Architect at Amazon Web Services. He works with customers to drive digital transformations while helping them architect, automate, and re-engineer solutions to fully leverage the AWS Cloud.
|