danielrvt
danielrvt

Reputation: 10926

Creating a Typescript NPM library

I have a modelsdirectory (my-models) in my project that contains a few important typescript classes for my app.

I've been using it from within the app with no problems and, now I want to make it an npm package so I can import it in another project.

This is what I tried to do:

  1. npm init in my-models directory (the one that contains all my models and classes)
  2. npm link in my-models directory (the one that contains all my models and classes)
  3. npm link my-models in another "client" project's root directory
  4. import * from "my-models" in some files of the client project

The problem I have is that no matter what I do, I can't find a way to share all my Typescript classes and use them in another project. I run into trouble compiling my library and then when I make it compile, I cannot import classes in my client project. I get this error:

`File '.../services/my-models/index.d.ts' is not a module.ts(2306)

This is the package.json of my-models:

{
    "name": "my-models",
    "version": "0.9.0",
    "description": "API Client and models",
    "main": "dist/main.js",
    "types": "index.d.ts",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "dependencies": {
        "axios": "^0.19.0",
        "@types/axios": "^0.14.0"
    },
    "devDependencies": {
        "typescript": "^3.9.5"
    }
}

And this is an import in my client project where I try to import one of my models:

import { Student } from 'my-models'

But wait, I kind of made it work doing this:

import { Student } from 'my-models/dist/main'

Why? I'm saying in my-models's package.json that dist/main.js is the main file, why can't I just import * from "my-models"?

BTW, this is my-models/dist directory:

enter image description here

So not sure if I'm doing something wrong or how to do it correctly. Appreciate any help

Upvotes: 4

Views: 2032

Answers (2)

Jason Goemaat
Jason Goemaat

Reputation: 29214

Thanks to Adrian's answer I was able to create a library the angular way. Looking into it more you only really require the ng-packagr package for development. It requires no typescript configuration or setup and one extra ng-package.json file with a line for the schema

I have a repo with more info in the README but here are the steps to create a base package:

  1. create a package with npm init
  2. install ng-packagr with npm install -D ng-packagr
  3. add build script to your package.json: "build": "ng-packagr -p ng-package.json"
  4. add a new file ng-package.json:
    {
      "$schema": "./node_modules/ng-packagr/ng-package.schema.json"
    }
    
  5. add a new file src/public_api.ts:
    export function add(a: number, b: number): number {
      return a + b
    }
    
  6. run npm build

That's it. The 'dist' directory contains your package. It can be published with npm publish dist. If you go into it you can run npm link and then use it from other projects on your computer with npm link <package-name> with whatever package name you have in the package.json.

I was able to link to it in a new vuetify project after using npm link my-package with this:

import { add } from 'my-packager'
console.log(`3 + 19 = ${add(3, 19)}`)

With a new node package I was able to use it in index.mjs with this:

import { add } from 'my-packager'
console.log(`7 + 2 = ${add(7,2)}`)

And with index.js like this:

import('my-packager').then(({ add }) => {
    console.log(`7 + 2 = ${add(52,-10)
}`))

This produces es2022 modules, if you want older versions I suppose you could use an older version of ng-packagr. If you want to include static assets you will have to look at the schema for ng-package.json.

Upvotes: 0

Adrian Brand
Adrian Brand

Reputation: 21638

I use the Angular CLI to build NPM libraries even if they are not Angular projects. You can just delete the Angular dependencies from the package.json file and you have a world class TypeScript project setup for you with a great test pipeline.

npm install --global @angular/cli
ng new my-lib --create-application=false

cd my-lib
ng generate library my-lib

After you generate the library you can go into the projects/my-lib/src directory open the package.json file and get rid of the Angular dependencies. Now you have a blank TypeScript project.

ng build my-lib will build it

ng test my-lib will run the unit test

cd into the dist/my-lib folder and you can npm publish straight to npm.

Why hand roll a TypeScript build when you can leverage off the work of the Angular team?

Upvotes: 4

Related Questions