Running TypeScript scripts on Angular code

I needed to check my Angular application for data consistency. Those checks included completeness of internally referenced data, as well as the existence of files referenced by file name in that data.

Since Angular is TypeScript, it would be nice to use TypeScript for those checks, as I can directly reference all types and data declared in the application code using the import mechanism.

(I had previously used gulp for such tasks, but used JavaScript at that time. Apparently, there also exists a way to integrate gulp with TypeScript)

To run a TypeScript from the command line, I installed ts-node as a dev dependency in my Angular application:

npm i -D ts-node

However, running the script using

npx ts-node path-to-script.ts

would raise the error message

(node:1060467) Warning: To load an ES module, set “type”: “module” in the package.json or use the .mjs extension.
(Use node --trace-warnings ... to show where the warning was created)

Fortunately, this issue was quite easy to resolve thanks to this SO comment, as I only needed to edit tsconfig.json to add the following configuration to the JSON root:

"ts-node": {
  "compilerOptions": {
    "module": "commonjs"
  }
}

Handling __ivy_ngcc_bak compiler errors

An Angular project I work on uses some custom libraries from a private repository. When making changes to the library, it is necessary to test locally, before publishing to the repository.

So how do you test your changes locally? I found it sufficient to copy the result of the ng-packagr script into the library’s directory of the project’s node_modules directory, run ng build, and you’re done.

This changed when Angular Ivy came along as we made the switch to Angular 10.

Suddenly, calling ng build after copying the packagr files resulted in multiple warnings stating

WARNING in Unable to fully load D:/path/to/web/node_modules/weblibrary/lib/filename.d.ts for source-map flattening: Circular source file mapping dependency: D:/path/to/web/node_modules/weblibrary/lib/filename.d.ts.map -> D:/path/to/web/node_modules/weblibrary/lib/filename.d.ts.map

and an error message

ERROR in Tried to overwrite D:/path/to/web/node_modules/weblibrary/lib/filename.d.ts.__ivy_ngcc_bak with an ngcc back up file, which is disallowed.

Well, I checked, and indeed, the file existed. Let’s delete the *.__ivy_ngcc_bak files, and run ng build again. I also found it necessary to delete the library’s __ivy_ngcc__ directory in the target project.

Run ng build again, and only the warnings are output. Run ng build once more, and the warnings are gone.


As I prepared this post, I wondered whether I had missing a solution that already exists for this problem.

I found npx install-from which seems to present itself as an alternative to npm link. I tried it, but unfortunately it stopped with an error message

D:\path\to\web>npx install-from D:\path\to\weblibrary\dist\weblibrary
npx: installed 5 in 3.016s
(node:14136) UnhandledPromiseRejectionWarning: Error: spawn npm ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:267:19)
at onErrorNT (internal/child_process.js:469:16)
at processTicksAndRejections (internal/process/task_queues.js:84:21)
(node:14136) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:14136) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

without any indication what might have gone wrong.

Note that if you run a module which is not installed locally, npx will download it every time from your configured repository. If you use a package more often, better install it locally running npm install -g package.


So I checked again, and found that npm install also supports installation from a folder, not only from repository.

Running npm install D:/path/to/web/node_modules/weblibrary/package replaced the library’s <DIR> entry under node_modules with a <JUNCTION> entry (i.e. symlink) pointing to the path given as parameter:

Install the package in the directory as a symlink in the current project. Its dependencies will be installed before it’s linked.

In the package directory, installing the package adds a node_modules directory, and running ng build also updates the package.json file in the package directory. The application’s package.json entry for the package is updated from a version-specific reference to the library in the repository to a “file:…” reference to the package directory.


Now it became clear what the install-from is trying to do:

  • run npm pack in the library directory to create a .tgz
  • run npm install from the .tgz in the application directory
  • it fails somewhere

As a work-around to recreate the functionallity of import-form, I call npm pack package-directory from the library’s directory, which creates a library-version.tgz file, and npm install from the .tgz in the application directory.


So I came up with 3 methods to update a library in an application:

  • Clean-up Ivy artifacts and inject ng-packagr result using xcopy
  • npm install from library’s ng-packagr directory
  • npm pack to .tgz and npm install from .tgz

Getting Started with Visual Studio Code and Angular2

Version 1.0 of Visual Studio Code has been released. Time to give it a try along with TypeScript and Angular2.

  • Download and install Visual Studio Code
  • Run Visual Studio Code
  • Check your settings regarding Updates and Telemetry (i.e. “phoning home”), and everything else
  • VS Code will start with the OS’es locale it it is supported. To change to English, create the file locale.json in your user directory C:\Users\[UserName]\AppData\Roaming\Code\User containing the lines
{
"locale":"en"
}

nodejs firewall

  • Navigate to http://localhost:3000, where :3000 is defined by the browser-sync nodes module