3

I have a NestJS application as part of an Angular / Nx workspace.

Within the nest application I'm using nestjs-console to run commands (e.g. to load fixture data).

Per the nestjs-console docs this involves:

  1. Creating a console.ts file
  2. Adding a script in package.json like "console:dev": "ts-node --project apps/api/tsconfig.console.json apps/api/src/console.ts"
  3. Calling it, e.g. with npm run console:dev -- --help

Now I have used Nx to create a lib of shared code between applications.

This works well for commands under Angular CLI (test; serve etc.), but the nestjs-console task understandably fails with:

Error: Cannot find module '@my-workspace/my-lib'

So the question is how to bring the nestjs-console command under the control of Angular CLI (or run NestJS commands in some other way).

I feel it should be possible to add a custom task to angular.json which uses an existing builder and then somehow points to the console command. (I don’t feel like I need a custom builder, but I could be wrong about that).

I’m stuck because I’m not so familiar with this environment, and angular.json workspace config.

Any help is appreciated, be it:

  • Advice on approaches
  • Examples I can copy
  • Specific pointers

EDIT

I tried using the NestJS Application Context directly, (rather than via nestjs-console) and per this blog post running it with ts-node.

This has the same problems as before. I believe this issue is something to do with how ts-node handles paths in tsconfg.

If I change the way the shared code is imported from:

import { HeadwordDto } from '@my-workspace/my-lib';

To:

import { HeadwordDto } from '../../../../../../libs/my-lib/src';

Then everything works, but tslint complains with "library imports must start with @my-workspace/ (nx-enforce-module-boundaries)." I can see how this defeats the point of Nx.

Alternatively, dealing with what I think is the paths issue looks a bit hairy and involves tools like tspath or module-alias. It also does not benefit from Nx goodness.

I have now added a new Architect target to angular.json which is just like the build target (using the @nrwl/node:build builder), except that is builds the desired application context:

"build-console": {
  "builder": "@nrwl/node:build",
  "options": {
    "main": "apps/api/src/console.ts",      // build console application context
    "outputPath": "different/output/path",  // can run alongside app
    ...
  }
},

After this is built then it can be run via node:

node ./different/output/path/main.js –help

EDIT 2

Building on the approach above, it's also possible to use the execute builder to build the console application context continually in a separate terminal window:

"serve-console": {
  "builder": "@nrwl/node:execute",
  "options": {
    "buildTarget": "api:build-console",
    "port": 7778,
    "args": ["--help"]
  }
},

From here I guess the next step could be to make the console application context into a separate app, with its own project in angular.json, and just pull in the needed code. Starting to feel like the Nx team are about 58 steps ahead of me ;-)

Not sure if this is the best solution, but it works. As before, any advice appreciated!

EDIT 3

To expand on this, in response to @Digitrance's question. The approach I ended up using was:

angular.json

{
    ...
    "api": {
      ...
      "architect": {
        ...
        "build-console": {
          "builder": "@nrwl/node:build",
          "options": {
            "outputPath": "dist/apps/api-console",
            "main": "apps/api/src/console.ts",
            "tsConfig": "apps/api/tsconfig.app.json"
          }
        },
        "serve-console": {
          "builder": "@nrwl/node:execute",
          "options": {
            "buildTarget": "api:build-console",
            "port": 7778,
            "args": ["--help"]
          }
        },

/my-repo/apps/api/src/console.ts

import { BootstrapConsole } from 'nestjs-console';
import { AppModule } from './app/app.module';

const bootstrap = new BootstrapConsole({
  module: AppModule,
  useDecorators: true
});
bootstrap.init().then(async app => {
  try {
    await app.init();
    await bootstrap.boot();
    process.exit(0);
  } catch (e) {
    console.error('Error', e);
    process.exit(1);
  }
});

And then commands to run the console:

ng run api:build-console
ng run api:serve-console

node ./dist/apps/api-console/main.js --help
node ./dist/apps/api-console/main.js myCommand

(Note that api was the name of my app).

Hope this helps!

1 Answer 1

1

Like you, I had trouble setting this up. My error boiled down to syntax errors, which according to some issues at ts-node github had to do with node not being able to read the imports properly because it was commonjs syntax. My solution was as followed:

  1. Add the tsconfig.console.json next to the tsconfig.app.json in your nx application.
  2. Make sure the tsconfig.console.json contains "module": "commonjs" inside the "compilerOptions". Other than that I copied tsconfig.app.json.
  3. In the package.json add the following line: "console:dev": "ts-node --project apps/api/tsconfig.console.json -r tsconfig-paths/register apps/api/src/console.ts" to your scripts.

Hope it helps you or anyone else.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for this. My feeling in the end was that ts-node in the nestjs-console docs was a red herring. One of the features of Angular CLI / nx is that it gives lots of ways of building TypeScript files into JS. I ended up doing the builds with new architect targets in angular.json, and not using ts-node.
@DerekHill Could you please share a code sample of your solution?
Ok @Digitrance. I have edited my question to include more sample code. Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.