André Pires
André Pires

Reputation: 51

How to solve angular custom library dependencies on node express?

I'm studying node express, particularly express written in typescript. I have the basic setup in place and can see my .ts files being converted to js in my dist folder. I have also created an angular 10 library and successfully published the library to npm registry.

This is the express project folder and file structure:

project-name
-src
--services
---api.ts
.env
package.json
tsconfig.json
tslint.json

package.json: please note the dependency to @mycompany/my-custom-lib

"scripts": {
    "prebuild": "tslint -c tslint.json -p tsconfig.json --fix",
    "build": "tsc",
    "prestart": "npm run build",
    "start": "node .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@mycompany/my-custom-lib": "0.0.1",
    "dotenv": "^8.2.0",
    "express": "^4.17.1"
  },
  "devDependencies": {
    "@types/dotenv": "^8.2.0",
    "@types/express": "^4.17.8",
    "@types/node": "^14.14.7",
    "tslint": "^6.1.3",
    "typescript": "^4.0.5",
    "ts-node": "8.6.2"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "esModuleInterop": true,
        "target": "es6",
        "noImplicitAny": true,
        "moduleResolution": "node",
        "sourceMap": true,
        "outDir": "dist",
        "declaration": true,
        "declarationMap": true,
        "strict": true
    },
    "include": ["src"]
}

src/index.ts:

import express from "express";
import https from "https";
import fs from "fs";
import dotenv from "dotenv";
import { TestApi } from "./services/api";

dotenv.config();
const port = process.env.SERVER_PORT;
const app = express();
const api = new TestApi();

// define a route handler for the default home page
app.get("/", (req, res) => {
    const lawyers = api.getLawers();
    res.send(lawyers);
});

https.createServer({
    key: fs.readFileSync('./src/server.key'),
    cert: fs.readFileSync('./src/server.crt')
}, app).listen(port);

src/services/api.ts

import { CustomerDataModel } from "@mycompany/my-custom-lib/lib/customer.datamodel";

export class TestApi {

    public getCustomers(): CustomerDataModel[] {

        const customer1 = new CustomerDataModel();
        customer1.id = '0001';
        customer2.name = 'Customer 1';

        const customer2 = new CustomerDataModel();
        customer2.id = '0002';
        customer2.name = 'Customer 2';

        const customers = [
            customer1,
            customer2
        ];

        return customers;
    }
}

When I execute npm run start, I get the following error:

Error: Cannot find module '@mycompany/my-custom-library/lib/customer.datamodel'
Require stack:
- C:\projects\test-angular-express\test-api\dist\services\api.js
- C:\projects\test-angular-express\test-api\dist\index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:965:15)
    at Function.Module._load (internal/modules/cjs/loader.js:841:27)
    at Module.require (internal/modules/cjs/loader.js:1025:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (C:\projects\test-angular-express\test-api\dist\services\api.js:4:28)
    at Module._compile (internal/modules/cjs/loader.js:1137:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
    at Module.load (internal/modules/cjs/loader.js:985:32)
    at Function.Module._load (internal/modules/cjs/loader.js:878:14)
    at Module.require (internal/modules/cjs/loader.js:1025:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'C:\\projects\\test-angular-express\\test-api\\dist\\services\\api.js',
    'C:\\projects\\test-angular-express\\test-api\\dist\\index.js'
  ]
}

Looking at the js generated code I see this: dist/services/api.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TestApi = void 0;
const customer_datamodel_1 = require("@mycompany/domain/lib/customer.datamodel"); // <- THIS iS FAILING
class TestApi {
    getCustomers() {
        const customer1 = new customer_datamodel_1.CustomerDataModel();
        customer1.id = '0001';
        customer1.name = 'Customer 1';
        const customer2 = new customer_datamodel_1.CustomerDataModel();
        customer2.id = '0002';
        customer2.name = 'Customer 2';
        const customers = [
            customer1,
            customer2
        ];
        return customers;
    }
}
exports.TestApi = TestApi;
//# sourceMappingURL=api.js.map

Upvotes: 0

Views: 1183

Answers (1)

Andr&#233; Pires
Andr&#233; Pires

Reputation: 51

For those who are interested, this is what I did:

I gave up on trying to make an Angular library to work as described in the question. Instead, I followed this the following tutorial to create a typescript library that is compatible with node and made little adjustments to make it compatible with Angular. By "compatible" I mean: I can npm install the library and use it normally in both Angular and node. Tutorial link: https://dev.to/charperbonaroo/creating-a-ts-written-npm-package-for-use-in-node-js-or-browser-5gm3

To make it work with Angular, I just added "declaration": true and "declarationMap": true to my tsconfig.json file, so the build generates the d.ts files.

Upvotes: 1

Related Questions