0%
May 2, 2025

How to Build an NPM Package?

npm-package

Resulting Package

Project Structure

We will explain the following important files:

  • tsconfig.json
  • package.json
  • index.ts

And to test our package we created another folder called test-folder.

Let's Develop our Package: secrets-manager-to-config

Folder secrets-manager-to-config/
index.ts
1import { downloadConfig } from "./src/env-pull"
2import { FileFormat } from "./src/SecretUtil"
3
4export {
5    downloadConfig, FileFormat
6}

Up to this part we have achieved "named export". Package consumers can import our functions via

import { downloadConfig, FileFormat } from "secrets-manager-to-config";

The default export cannot be destructured as above directly:

7export default {
8    downloadConfig, FileFormat
9};
package.json, setting homepage and repository info as well

The highlighted lines are important to identify the entrypoint of our transpiled ts project. The remaining come from npm init.

1{
2  "name": "secrets-manager-to-config",
3  "version": "1.0.11",
4  "description": "Pull secrets from secrets managers as nested json or yml file",
5  "scripts": {
6    "build": "tsc",
7    "test": "echo \"Error: no test specified\" && exit 1"
8  },
9  "types": "dist/index.d.ts",
10  "main": "dist/index.js",

Next to display the following

we add

11  "repository": {
12    "type": "git",
13    "url": "https://github.com/machingclee/pull-env-from-secrets-manager.git"
14  },
15  "homepage": "https://github.com/machingclee/pull-env-from-secrets-manager#readme",

Here the repository url comes from the https-clone option in github.

Finally we fill in the rest:

16  "keywords": [
17    "secrets-manager"
18  ],
19  "author": "machingclee",
20  "license": "MIT",
21  "devDependencies": {
22    "@types/js-yaml": "^4.0.9",
23    "ts-node": "^10.9.2",
24    "typescript": "^5.8.3"
25  },
26  "dependencies": {
27    "@aws-sdk/client-secrets-manager": "^3.799.0",
28    "@types/lodash": "^4.17.16",
29    "@types/minimist": "^1.2.5",
30    "js-yaml": "^4.1.0",
31    "lodash": "^4.17.21",
32    "minimist": "^1.2.8"
33  }
34}
tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "declaration": true,
    "outDir": "./dist",
    "strict": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["**/*.ts"],
  "exclude": ["node_modules", "dist"]
}
Build the package

We execute

yarn build

to execute our tsc script, which uses our tsconfig.json to identify the output directory.

Test our package before publishing it
Import the package locally

Let's cd into this folder:

Let's npm init and add our package into package.json:

{
  "dependencies": {
    "secrets-manager-to-config": "file:../secrets-manager-to-config",
    "tsm": "^2.3.0"
  }
}

We also added tsm for a light-weighted binary executing our ts file.

Now when we run yarn, it will install our package and its dependencies into the current project.

At this point we can write a test file to test the import:

// test-folder/env-pull.ts
import { downloadConfig, FileFormat } from "secrets-manager-to-config";

downloadConfig();
Modify the package and import it again for testing

After adjusting the original package, we

  1. yarn build in secrets-manager-to-config/
  2. Delete test-folder/node_modules
  3. cd into test-folder/ and run yarn to install everything again
Publish it

We need to

  1. npm login, and then
  2. npm publish