This documentation is not maintained. Please refer to doc.castsoftware.com/technologies to find the latest updates.


This extension was previously (in version 1.0, 1.1, and 1.2) known as TypeScript and Angular.


Summary: This document provides information about the extension providing TypeScript, Angular, React and Node support for Web applications.

Extension ID

com.castsoftware.typescript

What's new

See TypeScript and Frameworks - 1.10 - Release Notes for more information.

Description

This extension provides support for the TypeScript language. It also includes support for Angular, React, React-Native and some of the main frameworks for Node.js Web applications such as Express (when they are used within typescript source code).

  • TypeScript is an open-source programming  language. It is a superset of JavaScript that adds optional typing and that compiles to plain JavaScript.
  • Angular is a front-end web framework used to create modern web platform capabilities.
  • React and React-Native are frameworks for building user interfaces
  • Node.js is a run-time environment that executes JavaScript code outside of a browser thus allowing to develop the server-side of an application using TypeScript.
    • Express is a server web framework.
    • Fastify is a server web framework.
    • Axios is a promise based HTTP client.
    • Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
    • AWS is a cloud service by Amazon.
    • TypeORM is an Object-Relational Mapping framework.
    • Sequelize is a framework for database management.

Note that:

  • in order to analyze a JavaScript source code which uses Express or Fastify frameworks, you should use the Node.js extension.
  • similarly, in order to analyze a JavaScript source code which uses the Angular framework, you should use the AngularJS extension.
  • finally, in order to analyze a JavaScript source code which uses the React or React-Native framework, you should use the ReactJS extension.

In what situation should you install this extension?

The typical use case would be a full-stack web application developed entirely in TypeScript using Angular framework and Node.js. However, this extension should be used whenever any sub-set of the application is implemented using TypeScript (provided that you want to view the call-graph of that part of the application). 

Angular/TypeScript Front-end connected to Node.js/Express/MongoDB back-end

Supported versions

The following tables display the list of versions that this extension supports. It also gives a list of the supported frameworks for Node.js.

TypeScript

VersionSupported
1.x

(tick) 

2.x

(tick)

3.x

(tick)

4.x

(tick)

Angular

VersionSupported
2

(tick)

4

(tick)

5

(tick)

6

(tick)

7

(tick)

8(tick)
9(tick)
10(tick)
11(tick)
12(tick)
13(tick)

React

VersionSupported
15.x

(tick)

16.x

(tick)

React-Native

VersionSupported

0.x

(tick)

Supported Node.js versions

VersionSupport Comment
v0.x

(error)

No longer supported
v4.x

 (tick)

LTS
v5.x

 (tick)

Based on Javascript ES6
v6.x

 (tick)

Based on Javascript ES6
v7.x(tick)Based on Javascript ES6
v8.x

(tick)


v9.x

(tick) 


v10.x

(tick)


v11.x

(tick)


v12.x

(tick)


v13.x

(tick)


v14.x(tick)

Supported frameworks for Node.js

  • (tick) indicates that the framework is currently supported.
  • (error) indicates that the framework is not yet supported.

Library

Comment

Data Access

Web Service

or communication

Supported versions

ExpressNode.js application framework
(tick)4.x
MongooseMongoDB access(tick)
5.x
SequelizeNode.js application framework(tick)
5.x; 6.x
TypeORMORM(tick)
0.2.x
FastifyNode.js server
(tick)3.x
AxiosPromise based HTTP client
(tick)0.x
Node-mongodb-nativeMongoDB access(tick)
3.x
nestjsNode.js application framework
(tick)6.x; 7.x
httpsNode.js web service
(tick)
fetchJavaScript builtin web service
(tick)
requestHTTP request client 'request'
(tick)2.x

request-promise

HTTP request client 'request'
(tick)4.x
request-promise-nativeHTTP request client 'request'
(tick)1.x
request-promise-anyHTTP request client 'request'
(tick)1.x
Mongo-clientMongoDB access(error)

CouchdbCouchdb access(error)

Node-couchdbCouchdb access(error)

Couchdb-nanoCouchdb access(error)

MarklogicMarklogic access(error)

my_connectionMySQL access(tick)
0.x
pgPostgreSQL access(tick)
7.x; 8.x
oracledbOracle Database access(tick)
4.x; 5.x

node-sqlserver

MsnodeSQL access(tick)
0.x

mssql

MsSQL access(tick) 
5.x; 6.x
HapiNode.js application framework(error)

SailsNode.js application framework(error)(error)
LoopbackNode.js application framework

(error)

(error)
KoaNode.js application framework(error)

KnexNode.js SQL query builder (error)

MemcachedStorage framework(error)

AWS.DynamoDBAmazon database access(tick)
SDK 2.x; SDK 3.x
AWS.S3Amazon storage service(tick)
SDK 2.x; SDK 3.x
AWS.LambdaAmazon routing solution
(tick)

Cloudformation, Serverless framework, SAM

(requires com.castsoftware.cloudconfig)

AWS.SNSAmazon Simple Notification Service
(tick)SDK 2.x; SDK 3.x
AWS.SQSAmazon Simple Queue Service
(tick)SDK 2.x; SDK 3.x
Azure BlobsAzure storage service(tick)
@azure/storage-blob; azure-storage
Azure Service BusAzure Queue Service
(tick)@azure/service-bus; azure-sb

Supported Emailing frameworks: @sendgrid/mail, nodemailer

Files analyzed

Icon(s)FileExtension

TypeScript.ts

TypeScript.tsx

Skipped files

The TypeScript analyzer will automatically skip files inside folders (or sub-folders) that by convention pertain to either external libraries or unit-testing. Currently, the following are skipped:

  • Folders named as node_modules, e2e, e2e-bdd, e2e-app
  • Files with following name endings: .spec.ts, -spec.ts, _spec.ts, .d.ts

As mentioned in the introduction, TypeScript is a language that will be compiled to generate JavaScript files. Sometimes, the delivery will include these files, this is why the analyzer will skip the generated JavaScript files if we find their original TypeScript file.

Function Point, Quality, and Sizing support

This extension provides the following support:

  • Function Points (transactions): a green tick indicates that OMG Function Point counting and Transaction Risk Index are supported
  • Quality and Sizing: a green tick indicates that CAST can measure size and that a minimum set of Quality Rules exist

Function Points
(transactions)
Quality and Sizing
TypeScript(tick)(tick)
Angular(tick)(tick)
React(tick)(tick)
Express(tick)(error)
Mongoose(tick)(error)
Sequelize(tick)(error)
TypeORM(tick)(error)

CAST AIP compatibility

This extension is compatible with:

CAST AIP release

Supported

8.3.x(tick)
8.2.x(tick)

Supported DBMS servers

This extension is compatible with the following DBMS servers:

CAST AIP releaseCSS/PostgreSQLOracleMicrosoft
All supported releases(tick)(tick)(tick)

Prerequisites

(tick)An installation of any compatible release of CAST AIP (see table above)

Dependencies with other extensions

Some CAST extensions require the presence of other CAST extensions in order to function correctly. The TypeScript and frameworks extension requires that the following other CAST extensions are also installed:

Note that when using the CAST Extension Downloader to download the extension and the Manage Extensions interface in CAST Server Manager to install the extension, the HTML5/JavaScript, ReactJS and NodeJS extensions will be installed automatically. You do not need to do anything.

Download and installation instructions

Please see:

The latest release status of this extension can be seen when downloading it from the CAST Extend server.

Packaging, delivering, and analyzing your source code

Once the extension is downloaded and installed, you can now package your source code and run an analysis. The process of packaging, delivering and analyzing your source code is described below:

Click here to expand...

Packaging and delivery

Note that the TypeScript and Angular extension does not contain any CAST Delivery Manager Tool discoverers or extractors, therefore, no "TypeScript and Angular" projects will be detected by the CAST Delivery Manager Tool. You therefore have two choices:

  • manually create an Analysis Unit in the CAST Management Studio.
  • or download and install the Web Files Discoverer to automatically detect projects in the CAST Delivery Manager and therefore Analysis Units in the CAST Management Studio.

Using the CAST Delivery Manager Tool:

  • create a new Version
  • create a new Package for your TypeScript and Angular source code using the Files on your file system option:

  • Define the root folder of your Application source code:

  • Run the Package action
  • Before delivering the source code, check the packaging results:
Without the Web Files Discover

If you are not using the Web Files Discoverer, the following will occur:

  • the CAST Delivery Manager Tool will not find any "projects" related to the TypeScript and Angular application source code - this is the expected behaviour. However, if your TypeScript and Angular related source code is part of a larger application (for example a JEE application), then other projects may be found during the package action (click to enlarge):

With the Web Files Discoverer

If you are using the Web Files Discoverer, the following will occur:

  • the CAST Delivery Manager Tool will automatically detect "HTML5 file projects" (see Web Files Discoverer for more technical information about how the discoverer works) related to the TypeScript and Angular application source code. In addition, if your TypeScript and Angular related source code is part of a larger application (for example a JEE application), then other projects may also be found during the package action (click to enlarge):

  • Deliver the Version

Analyzing

Using the CAST Management Studio:

  • Accept and deploy the Version in the CAST Management Studio.
Without the Web Files Discover

If you are not using the Web Files Discoverer, the following will occur:

  • No Analysis Units will be created automatically relating to the TypeScript and Angular source code - this is the expected behaviour. However, if your TypeScript and Angular related source code is part of a larger application (for example a JEE application), then other Analysis Units may be created automatically:

  • In the Current Version tab, add a new Analysis Unit specifically for your TypeScript and Angular source code, selecting the Add new Universal Analysis Unit option:

  • Edit the new Analysis Unit and configure in the Source Settings tab:
    • a name for the Analysis Unit
    • ensure you tick the HTML5/JavaScript option (the TypeScript and Angular extension depends on the HTML5 and JavaScript extension - and therefore the Universal Analyzer language for the AngularJS extension is set as HTML5/JavaScript)
    • define the location of the deployed TypeScript and Angular source code (the CAST Management Studio will locate this automatically in the Deployment folder):

  • Run a test analysis on the Analysis Unit before you generate a new snapshot.
With the Web Files Discoverer

If you are using the Web Files Discoverer, the following will occur:

  • "HTML5" Analysis Units will be created automatically (see Web Files Discoverer for more technical information about how the discoverer works) related to the TypeScript and Angular application source code. In addition, if your TypeScript and Angular related source code is part of a larger application (for example a JEE application), then other Analysis Units may also be created:

  • There is nothing further to do, you can now run a test analysis on the Analysis Unit before you generate a new snapshot.

What results can you expect?

Once the analysis/snapshot generation has completed, you can view the results in the normal manner:


In this full-stack example, the front-end is implemented in TypeScript and uses Angular and the back-end is implemented in JavaScript and uses Express and MongoDB. If analyzing a web-application with the back-end implemented in TypeScript, the data-base access would be missing since this extension does not yet support any database access framework.

Objects

The following objects are identified:

IconMetamodel nameCode Reference (example)

Typescript Module

Typescript Namespace
namespace A {
     
    // not exported
    function a() {
    }
}

Typescript Class
export class TodoStorage implements ... {


...     
}

Class Initializer
export class TodoStorage implements ... {

field = new Todo();

...     
}

Typescript Method
export class TodoStorage implements ... {

	// Standard method
	getTodos(): Observable<Todo[]> {
	}


	// Arrow method
	m1 = () => {alert("m1 is called")}     
}

Typescript Interface
export interface ITodoScope extends... {


...     
}

Typescript Function
// Named function
function add(x, y) {
    return x + y;
}

// Anonymous function
function(x, y) { return x + y; };


// Arrow function
var f = (x,y) => { return x + y };


// Anonymous arrow function
(x,y) => x+y;

// Generator function
function* infiniteSequence() {
    var i = 0;
    while(true) {
        yield i++;
    }
}

Angular Component

Angular Directive

Angular GET http service

TypeScript GET http service


Angular POST http service

TypeScript POST http service


Angular PUT http service

TypeScript PUT http service


Angular DELETE http service

TypeScript DELETE http service


HTML5 HTML fragment


ReactJS Application

ReactJS Component

ReactJS Form

Node.js Delete Operation Service
Node.js Get Operation Service
Node.js Post Operation Service
Node.js Put Operation Service

Node.js MongoDB connection

Node.js MongoDB collection

TypeScript SQL query

Node.js AWS SQS Publisher
Node.js AWS SNS Publisher
Node.js Azure Service Bus Publisher


Node.js AWS SQS Receiver
Node.js AWS SNS Subscriber
Node.js Azure Service Bus Receiver


Node.js AWS Unknown SQS Publisher
Node.js AWS Unknown SNS Publisher
Node.js Azure Unknown Service Bus Publisher


Node.js AWS Unknown SQS Receiver
Node.js AWS Unknown SNS Subscriber
Node.js Azure Unknown Service Bus Receiver


Node.js Call to Lambda

Node.js Call to unknown Lambda

Node.js S3 Bucket
Node.js Azure Blob Container

Node.js S3 Unknown Bucket
Node.js Azure Unknown Blob Container

More about Typescript analysis 

Click here to expand...

Support of arrow functions and methods

Arrow functions which have been introduced in typescript following ES6 standard (also known as ES2015) are supported. Since arrow functions are equivalent to standard functions, the same function objects are created by the analyzer for both standard functions and arrow functions. Arrow functions can also define methods in which case method objects are created by the analyzer. Examples of arrow functions and methods are provided in the Objects section of this documentation.

Support of anonymous functions

For anonymous functions, the analyzer creates function objects named <Anonymous$i> where $i is incremented such that each anonymous function object has a unique fullname.

Web Services

XMLHttpRequest

The analysis of the following code will create a TypeScript GET http service named "foo/url" and a callLink between my_func function and that service :

function my_func(){

  var xhttp = new XMLHttpRequest();
  xhttp.open("GET", "foo/url", false);
  xhttp.send();

}

 

fetch

The analysis of the following code will create a TypeScript POST http service named "foo/url" and a callLink between my_func function and that service :

function my_func(){
  const response = await fetch('foo/path', {
    method: 'POST'
  })
}

Window variable

The JavaScript window variable can be used to pass values such as urls. The windows variable is accessible from all modules. So when analyzing the following modules:

module1.py
window.myurl = "foo/url/"
module2.py
function my_func(){

  var xhttp = new XMLHttpRequest();
  xhttp.open("GET", window['myurl'], false);
  xhttp.send();

}

a webservice object is created with the url set through the window variable: 

More about Angular framework analysis

Click here to expand...

Web Services

Angular web services are supported for both the older Http and new HttpClient (Angular ≥4.3) libraries. The method calls get, post, put, delete, jsonp, and request are recognized.

example web services
import { HttpClient } from '@angular/common/http';

// web-service_GET.ts
 
export class ExampleService {

  constructor(private http: HttpClient) { }
  getData() {
    const url = "http://httpbin.org/get";
    return this.http.get(url);
  }
}

The results of this code snippet are shown below.:

Finally the use of the rxjs/ajax API as web service call is also supported. The different types of web services (GET, POST, PUT, DELETE) are represented with the same Angular objects we have used above, despite they are not restricted to the Angular framework.

Angular components and HTML fragments

In addition to the basic TypeScript objects the analyzer will generate specific objects and links for the Angular framework. In the following example, the analyzer creates a TypeScript module object associated with the file and a TypeScript class object associated with the decorated class MyComponentAngular components objects are created when finding special class decorators with the name Component. The view of Angular components is described in HTML language and the associated code can be either found in an external .html file or embedded in the decorator metadata. 

Link to html fragments
// example.ts
 
@Component({
  selector: 'click-me',
  template: `
    <button (click)="onClickMe()">Click me!</button>
    {{clickMessage}}`
})
export class MyComponent {
}

For embedded data, the analyzer creates an HTML5 HTML Fragment belonging to the component, and will automatically generate a use (U) link between the Component and the HTML fragment:

The generation of these links is necessary to describe the higher level call flow abstracted in the Angular framework and thus to retrieve transactions.

Environment variables

In our analysis, we consider a production deployment scenario. Thus we mimic the behavior of Angular when overloading behind-the-scenes the variables declared inside the exported environment dictionary defined in environment.ts  by those defined in environment.prod.ts. Global variables might be used to connect different technology layers (via URLs for example), thus retrieving them correctly can be critical for full transactions. The latest versions of Angular allow using many different production files. We only support a single production environment file, the standard environment.prod.ts. When using a no-production environment file a warning message will be logged.

// environment.ts
export const environment = { 
  production: false,
  urls = { .... }   // urls used for development
};


// environment.prod.ts
export const environment = { 
  production: true,
  urls = { .... }   // production urls
};

Injection with useValue

Dependencies are services or objects that a class needs to perform its function. Dependency injection, or DI, is a design pattern in which a class requests dependencies from external sources rather than creating them. 
The useValue key allows associating a fixed value with a Dependency Injection (DI) token. This is often used to provide runtime configuration constants such as website base addresses.

For instance, in the following, the Angular module provides an "environment" value.

import {Environment} from 'path/to/environmentinterface';
import { NgModule } from '@angular/core';

const environment: Environment = {
  my_url: "foo/path"
}

@NgModule({
  providers: [
    { provide: Environment, useValue: environment}
  ]
})
export class AppModule { 
}

This value can be accessed by other components through the constructor (note that the Type given to the "env" variable is the same as the one given in the provide key (see previous source code).

import { HttpClient } from '@angular/common/http';
import { Environment } from 'path/to/environmentinterface';
import { Component } from '@angular/core';


@Component()
export class FooClass{
  constructor (private http: HttpClient, private env : Environment){}

  getData() {
    const url = env.my_url;
    return this.http.get(url);
  }
}

Analyzing the previous modules will create a web service with the URL given through injection:  

Known limitations

  • Connectivity between components through Angular routing is not supported.
  • The support of TypeScript Map is limited. See the section Support of TypeScript Map to see which cases are supported.
  • Use of HttpRequest in Angular is not supported.

More about React and React-Native framework analysis

Click here to expand...

ReactJS Application

This declaration will create a ReactJS application named App:

ReactDOM.render(
  <AppContainer>
    <Provider store={store}>
      <App version={appVersion} />
    </Provider>
  </AppContainer>,
  appElement
);

ReactJS Component

This declaration will create a ReactJS component named Sequence because the class inherits from Component (a class that inherits from PureComponent would also induce the creation of a ReactJS component). A component must contain a render method. The render method is automatically called when the component is referred to in an HTML fragment:

import React, { Component } from 'react';
 
 class Sequence extends Component {
 
  shouldComponentUpdate(nextProps) {
    return this.props.positionFrom !== nextProps.positionFrom ||
      this.props.sequence !== nextProps.sequence ||
      this.props.nucleotidesPerRow !== nextProps.nucleotidesPerRow ||
      this.props.rowHeight !== nextProps.rowHeight;
  }
 
  render() {
    return (
      <g>
        {this.props.sequence.map((nucleotide, index) =>
          <Nucleotide
            type={nucleotide}
            position={this.props.positionFrom + index}
            key={index}
            index={index}
            onClick={this.props.onNucleotideClick}
            {...this.props}
          />,
        )}
      </g>
    );
  }
}

ReactJS Form

This declaration will create a ReactJS form named contact:

import React from 'react'
import { Field, reduxForm } from 'redux-form'

let ContactForm = props => {
  const { handleSubmit } = props
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="firstName">First Name</label>
        <Field name="firstName" component="input" type="text" />
      </div>
      <div>
        <label htmlFor="lastName">Last Name</label>
        <Field name="lastName" component="input" type="text" />
      </div>
      <div>
        <label htmlFor="email">Email</label>
        <Field name="email" component="input" type="email" />
      </div>
      <button type="submit">Submit</button>
    </form>
  )
}

ContactForm = reduxForm({
  // a unique name for the form
  form: 'contact'
})(ContactForm)

HTML fragment

This declaration will create a HTML fragment named render_fragment_1 starting with "<g>" and ending with "</g>". There can be several fragments in any function/method:

render() {
  return (
    <g>
      {this.props.sequence.map((nucleotide, index) =>
        <Nucleotide
          type={nucleotide}
          position={this.props.positionFrom + index}
          key={index}
          index={index}
          onClick={this.props.onNucleotideClick}
          {...this.props}
        />,
      )}
    </g>
  );
}

Links from the ReactJS application

  • A relyon link is created from the application to the HTML fragment of the application.
  • A call link is created from the fragment to the ReactJS component referred to in the fragment
  • A call link is created from the component to the render method of the class representing the component (as the render method is automatically called).
  • A call link is created from the render method to the fragment contained inside the render method

Please remember that components are called mainly from html fragments, and render methods are implicitly called from ReactJS components.

Links from a HTML fragment

HTML tags present in HTML fragments are linked to ReactJS components if they exist:

    <g>
        <ChildrenLoading
			 dispatch={props.dispatch}
          	 {...this.props}
		/>
    </g>

HTML tags present in HTML fragments can also be linked to a Typescript function. HTML fragments are linked to functions or methods when they are represented between { ... }:

<UserSearchSelect
  dispatch={props.dispatch}
  label={formatMessage({ defaultMessage: 'Transfer to...' })}
/>

Node support

More about the support of custom node packages

Click here to expand...

It is possible to developp custom node packages. Apackageis a file or a directory that is described by apackage.jsonfile.

An application can combine mutliple packages. The packages can be built together using npm. npm adds these packages to a node_mudules directory. Note that the analyzer will skip everything which is inside a node_modules directory. Users should provide their custom packages at the root of the analyzed source code.


Let's consider a package named my_proj. The root dir contains a package.json file which defines the project name.

my_proj/package.json
{ "name": "@myprojname"
}

Everything which is exported (or re-exported) from the my_proj/src/index.ts can be imported from any project which uses this package. 

my_proj/src/index.ts
export function my_func(){
}

For instance when an other package uses this package, it can import the my_func function using the name of the package for the import:

otherproj/src/foo.ts
import {my_func} from '@myprojname'


function other_func(){
  my_func()	
}

When analyzing these source code, a callLink will be created between other_func and my_func:

More about emailing services: nodemailer and sendgrid/mail

Click here to expand...

When analyzing the following source code, an email object is created with a callLink from the my_send_mail function

import * as nodemailer from 'nodemailer';

async function my_send_mail() {
  let transporter = nodemailer.createTransport({
    //...
  });

  // send mail with defined transport object
  let info = await transporter.sendMail({
    from: '"Fred Foo" <foo@example.com>', // sender address
    to: "bar@example.com, baz@example.com", // list of receivers
    //...
  });
}


Similarly when analyzing the following source code, an email object is created with a callLink from the my_send_mail function:

const sgMail = require('@sendgrid/mail');

function my_send_mail(msg){
  sgMail
   .send(msg)
}


More about supported Nodejs built-in modules 

Nodejs comes along with several built-in modules. Here is a description of the support we provide for some of these modules.

Http, Http2, Https modules

Click here to expand...

This extension currently supports the use of these modules for http requests from the client-side only (i.e. the use of these modules as server is not yet supported).

The analysis of the previous code will generate Node.js Get HttpRequest service object which is called by my_request function. A link between my_request function and the anonymous handler function is also added. 

import * as https from "https"

function my_request(){
  https.get('https://encrypted.google.com/', (res) => {
    console.log('statusCode:', res.statusCode);
    console.log('headers:', res.headers);
}

More about nestjs framework analysis

Click here to expand...

Nest (NestJS) is a framework for building Node.js server-side applications. Nest provides a level of abstraction above many common Node.js frameworks. The following features provided by nestjs are supported.

Controllers

A controller's purpose is to receive specific requests for the application. A controller is defined using a classe@ and decorators.

The analysis of the following code will create a Node.js Get Operation named cats/all/ with a call link from the operation to the handler method findAll. The URL corresponds to the concatenation of the argument of the @Controller decorator with that of the @Get decorator of the method. The decorator of each method defines the type of the operation

import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Get('/all')
  findAll(): string {
    return 'This action returns all cats';
  }}

Middlewares

Middleware is a function that is called before the route handler. For instance, in the following source code, the logger function will be called before each handler of the CatsController. Our analyzer will create a callLink between the operations defined in the CatsController and the logger.

import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
export function logger(req: Request, res: Response, next: Function) {
  console.log(`Request...`);
  next();
};

@Module({
  imports: [CatsModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(logger)
      .forRoutes(CatsController);
  }
}

HTTP module

Nestjs allows performing http requests using the HTTP module. The analysis of the following source code will create a Node.js Get HttpRequest named foo/path/ with a call link from the findAll method to that request:

import { HttpService, Injectable, Logger } from '@nestjs/common';

@Injectable()
export class CatsService {
  constructor(private httpService: HttpService) {}

  findAll(): Observable<AxiosResponse<Cat[]>> {
    return this.httpService.get('foo/path');
  }
}

Known limitations

All nestjs features which are not documented here are not supported. 

More about Express framework analysis

Click here to expand...

The analysis of the following code will create a Node.js Get Operation named /login with a call link from the operation to the handler function f:

var app = express()
function f(req, res) {
    console.log('login ' + req.url);
    var currentSession = getSessionId(req, res);
}
app.get('/login', f);

Routers are also supported and the analysis of the following code will create a Node.js Get Operation named /foo1/foo2:

import express from 'express';

var router = express.Router()

// define the about route
router.get('/foo2', function (req, res) {
  res.send('About birds')
})

var app = express()
app.use('/foo1', router)

More about fastify framework analysis

Click here to expand...

The analysis of the following code will create a Node.js Get Operation named /login/{} with a call link from the operation to the handler function f:

import * as fastify from 'fastify'

function f(request, reply) {
   reply.send({ hello: 'world' })
}

const server: fastify.FastifyInstance<Server, IncomingMessage, ServerResponse> = fastify({})
// Declare a route
server.get('/login/:name', f)


Supported fastify methods are: get, put, post, delete, route

Known limitations

  • prefixes are not supported
  • fastify-mongodb is not supported

More about request, request-promise, request-promise-native, and request-promise-any frameworks

Click here to expand...

The analysis of the following code will create a Node.js Post HttpRequest named foo/post/ with a call link from my_func to that request:

import * as rp from 'request-promise-native'

function my_post(){
  var options = {
    method: 'POST',
    uri: 'foo/post',
    body: {
        some: 'payload'
    },
    json: true // Automatically stringifies the body to JSON
  };
 
  rp(options)
    .then(function (parsedBody) {
        // POST succeeded...
    })
    .catch(function (err) {
        // POST failed...
    });
}

Similar support is provided for request, request-promise, and request-promise-any frameworks.

More about axios framework analysis

Click here to expand...

The analysis of the following code will create a Node.js Put HttpRequest named foo/put/ with a call link from my_func to that request:

import * as axios from 'axios';

function my_func(){
  axios('foo/put', {method:'put'})

     .then(function (response) {
       // handle success
       console.log(response);
     })
}

More about Sequelize framework analysis

Click here to expand...

Sequelize is a promise-based Node.js ORM for Postgres, MySQL, MariaDB, SQLite and Microsoft SQL Server. In sequelize, the user defines Models for data storage. The models are modelized as tables. The following links are added for these API calls:

Link typeAPI
useInsertLinkcreate, bulkCreate
useSelectLinkfindAll, findByPk, findOne, findOrCreate,
findAndCountAll, count, max, min, sum
useUpdateLinkupdate, restore, increment, decrement
useDeleteLinkdestroy

The query API is also supported and a Query object is created as a result.

Example

In the following code: 

import * as Sequelize from 'sequelize';

const Model = Sequelize.Model;
class User extends Model {}
User.init({
  // attributes
  firstName: {
    type: Sequelize.STRING,
    allowNull: false
  },
  lastName: {
    type: Sequelize.STRING
    // allowNull defaults to true
  }
}, {
  sequelize,
  modelName: 'user'
  tableName: 'users'
  // options
});
function myfind(){
	User.findAll().then(users => {
  	console.log("All users:", JSON.stringify(users, null, 4));
	});
}

...the User class defines a model which is linked with the table named 'users' (through the User.init() call). The name of the table is defined by the tableName value which if not defined is set to the pluralized (if freezeTableName is not set to true) value of modelName which is itself set to the class name when it is not explicitly defined. The User.findAll() call then selects elements from that table 'users'.

In this example, this extension creates a useSelect link to the table 'users':

Note that a model can also be defined using method sequelize.define().

The Sequilize framework query method is not supported: if there any calls to database procedures using the Sequilize API query method, then missing links are expected.

More about TypeORM framework analysis

Click here to expand...

Connection

TypeORM can be used both with SQL and NoSQL databases. The database type is set through the connection option type

import {createConnection, Connection} from "typeorm";

const connection = await createConnection({
    type: "mysql",
    host: "localhost",
    port: 3306,
    username: "test",
    password: "test",
    database: "test"
});

The only NoSQL database which is supported by TypeORM is mongodb. A connection object is created by our analyzer only for mongodb databases. The name of the connection is the URL mongodb://localhost/test which is constructed using the host and database values.

An Entity is a class that maps to a database table (or collection when using MongoDB):

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    isActive: boolean;

}

When a mongodb database is used, for each entity, the extension creates a MongoDB collection object. A parentLink between that collection and the corresponding connection is added. For an SQL connection, the entity will be associated with the SQL table having the same name (if that table exists).

Link to table/collection

TypeORM provide several ways to access and/or update a table or collection. One can use an entity manager, a repository, or a query builder.

Here is an example with a repository:

import {getRepository} from "typeorm";
import {User} from "./user";

function update_user(){
    const userRepository = getRepository(User); 
    const user = await userRepository.findOne(1);
    user.name = "fooname";
    await userRepository.save(user);
}
  • The userRepository.findOne(1) method call generates a "useSelectLink" to the User table/entity.
  • The userRepository.save(user) method call  generates a "useUpdateLink" to the User table/entity.

Example for a mongodb database: both useSelect and useUpdate links are created between the update_user function and the User entity which belongs to the <Default> connection:

Example for a SQL database: both useSelect and useUpdate links are created between the update_user function and the user table. 

Cascades

Cascades are supported.
In the following example, the User entity has its column profile with a one-to-one relation with the Profile entity and cascade set to true:

import {Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn} from "typeorm";
import {Profile} from "./profile";

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @OneToOne(type => Profile, {
        cascade: true
    })
    @JoinColumn()
    profile: Profile;

}

When the profile column of a user instance is saved, if the profile column of that instance was updated with a profile instance, that profile instance is also saved.

import {getRepository} from "typeorm";
import {User} from "../entity_dir/user";
import {Profile} from "../entity_dir/profile";


function update_user(){
    const userRepository = getRepository(User); 
    const user = await userRepository.findOne(1);
    const profile = new Profile()
    user.name = "fooname";
    user.profile = profile
    await userRepository.save(user);
}

In the previous example, a useUpdate link is created between the update_user function and both the user and profile tables/entities:

SQL queries

Plain SQL queries can also be carried out using typeORM such as with the following code:

import {getConnection} from "typeorm";

export class A {
    public foo() {
        const manager = getConnection().manager;
        const rawData = await manager.query(`SELECT * FROM USER`);
    }
} 

In that example, a TypeScript query object is created and a callLink between the foo method and that query is added. The SQL Analyzer can then link that query with the corresponding table:

Known limitations

The following features are not supported

  • use of ormconfigs.yml, ormconfigs.env and ormconfigs.xm ORM configuration files 

  • custom repositories

  • view entities

  • entity listeners and subscribers

  • connectionManager

More about Mongoose and Mongodb frameworks analysis

See MongoDB support for Node.js source code.

Migration Issue when moving from com.castsoftawre.typescript 1.3.x to >= 1.4.x

Click here to expand...

In 1.3.x, MongoDB Connection and MongoDB Collection objects were added to Typescript Module objects and when a connection (or a collection) is accessed using Mongoose from several files, the analyzer was creating one connection (or collection) object per such file.
In versions >=1.4.x, MongoDB Connection and MongoDB Collection objects are added at the application level and when a connection (or a collection) is accessed using Mongoose from several files the analyzer creates only one connection (or collection).

In order to avoid "added objects" and minimize the number of "deleted objects" when updating from 1.3.x to >=1.4.x a migration is carried out. This migration requires com.castsoftware.internal.platform version >= 0.8.5 to be used.


Note that if the same connection (or collection) is accessed from different ts modules when analyzing with com.castsoftware.typescript 1.3.x several MongoDB Connection (or MongoDB Collection) objects are created whereas only one object is created with versions >=1.4.x. In such case, there would be "deleted objects" during the migration.

More about Azure services analyses

Azure Service Bus

Click here to expand...

NodeJS Azure Service Bus Publisher and NodeJS Azure Service Bus Receiver objects are created when the following methods are used:

Object created

Methods from ServiceBusClient from @azure/service-bus package


Methods from ServiceBusService from azure-sb package
NodeJS Azure Service Bus Publisher

sendMessages,
scheduleMessages

createSender, createReceiver
NodeJS Azure Service Bus ReceiverreceiveMessages, peekMessages, subscribe, getMessageIterator, receiveDeferredMessagesreceiveQueueMessage, receiveSubscriptionMessage

The name of the object created is that of the Queue (or the Topic). Whenever the evaluation of the Queue (or Topic) name fails, an Unknown object is created.
For publishers, a callLink  from the callable object (usually Function or Method) containing the call (to the supported method) to the publisher is added (see example below).
For receivers, some APIs (such as the subscribe API) require providing a handler function, in such case a callLink is created from the receiver to that handler. In other cases, a callLink is added from the receiver to the callable object (usually a Function or a Method) containing the call to the supported method (see example below).
Whenever an Azure Service Bus Publisher has the same name as an Azure Service Bus Receiver, the web service linker extension will create a call link from the Publisher to the Receiver.

Example

When analyzing the following source code:

import { ServiceBusClient, ServiceBusMessage, ServiceBusMessageBatch } from "@azure/service-bus";

function my_publish(Messages){
	const sbClient = new ServiceBusClient(connectionString);
    const sender = sbClient.createSender("MyQueue");
	await sender.sendMessages(Messages);
}

function my_receive(){
    const sbClient = new ServiceBusClient(connectionString);
	let receiver = sbClient.createReceiver("MyQueue", {
		receiveMode: "receiveAndDelete"
	});
	let messages = await receiver.receiveMessages(1);
}

you will get the following result:

Azure Blobs

Click here to expand...

When a source code contains calls to the APIs listed in the following table, this extension will create a link to Azure Blob objects. 

LinkType

Methods from containerClient

import {BlobServiceClient} from "@azure/storage-blob";
const blobServiceClient = new BlobServiceClient(...);
const containerClient = blobServiceClient.getContainerClient(...)

Methods from BlobClients (blockBlobClient,
PageBlobClient, AppendBlobClient or BlobBatchCLient)

import {BlobServiceClient} from "@azure/storage-blob"
const blobServiceClient = new BlobServiceClient(...)
const containerClient = blobServiceClient.getContainerClient(...)
const blockBlobClient = containerClient.getBlockBlobClient(...)

Methods from BlobServices

import * as azure from 'azure-storage'
const blobService = azure.createBlobService(...)
useInsertuploadBlockBlobsyncUploadFromURL, upload', uploadPages, uploadPagesFromURL, beginCopyFromURLcreateAppendBlobFromBrowserFile, createAppendBlobFromLocalFile, createAppendBlobFromStream, createAppendBlobFromText, createBlobSnapshot, createBlobSnapshot, createBlockBlobFromLocalFile, createBlockBlobFromStream, createBlockBlobFromText, createBlockFromStream, createBlockFromText, createBlockFromURL, createOrReplaceAppendBlob, createPageBlob, createPageBlob, createPageBlobFromLocalFile, createPageBlobFromStream, createPagesFromStream, createWriteStreamToBlockBlob, createWriteStreamToBlockBlob, createWriteStreamToNewAppendBlob, createWriteStreamToNewPageBlob, startCopyBlob
useUpdateuploadBlockBlobcommitBlockList, stageBlock, stageBlockFromURL, syncUploadFromURL, upload, uploadBrowserData
'ploadData, uploadFile, uploadStream, uploadPages, uploadPagesFromURL, appendBlock, appendBlockFromURL, beginCopyFromURL, startCopyIncremental
appendBlockFromStream, appendBlockFromText, appendFromBrowserFile, appendFromLocalFile, appendFromStream, appendFromText, commitBlocks, createAppendBlobFromBrowserFile, createAppendBlobFromLocalFile, createAppendBlobFromStream, createAppendBlobFromText, createBlobSnapshot, createBlockBlobFromLocalFile, createBlockBlobFromStream, createBlockBlobFromText, createBlockFromStream, createBlockFromText, createBlockFromURL, createOrReplaceAppendBlob, createPageBlob, createPageBlob, createPageBlobFromLocalFile, createPageBlobFromStream, createPagesFromStream, createWriteStreamToBlockBlob, createWriteStreamToBlockBlob, createWriteStreamToExistingAppendBlob, createWriteStreamToExistingAppendBlob, createWriteStreamToExistingPageBlob, startCopyBlob
useDeletedeleteBlob, deleteIfExistsclearPages, deleteBlobs, delete, deleteIfExistsdeleteBlob, deleteBlobIfExists, deleteContainer, deleteContainerIfExists
useSelect
getBlockList, query, createSnapshot, download, downloadToBuffer, downloadToFile, beginCopyFromURL, startCopyIncrementalcreateBlobSnapshot, createReadStream, getBlobToLocalFile, getBlobToStream, getBlobToText, startCopyBlob, createBlockFromURL

Example

When analyzing the following code, a blob container named my_container is created as well as a useInsert and a useUpdate links from the main function to that container  

import { BlobServiceClient } from "@azure/storage-blob";

const blobServiceClient = new BlobServiceClient(account_url, defaultAzureCredential);

async function main() {
  const containerClient = blobServiceClient.getContainerClient("my_container");
  const content = "Hello world!";
  const blockBlobClient = containerClient.getBlockBlobClient("blobName");
  const uploadBlobResponse = await blockBlobClient.upload(content, content.length);
}

 

More about AWS services analysis

AWS lambda

Click here to expand...

Lambda services allow executing some source code on the cloud. The execution can be set to be triggered by some AWS events. 

Lambda functions can be deployed using several deployment frameworks. The supported deployment frameworks are listed on this page.

When a lambda function is created and its runtime is nodejs, the current extension is responsible for linking the lambda objects and their triggers with the TypeScript handler functions.

Example

Let us consider a source code defining a lambda function that has two triggers: an SQS queue and an API Gateway. The lambda function has a nodejs runtime and the handler function is given by the handler function fullname. 

If the lambda function is deployed using a supported deployment framework (such as CloudFormation), the analysis will create a lambda function, an SQS receiver, and an API Gateway objects. Each of these objects has a runtime property (nodejs) and a handler property with the function fullname. 

If the current extension finds a TypeScript function matching the handler fullname a link to that function will be added from the lambda function, the SQS queue, and the API Gateway objects.

Click to enlarge

Lambda invocation using SDK

The SDK provides APIs to execute (i.e. invoke) lambda function.

The following APIs are supported:

  • invoke method of the Lambda "aws-sdk" client of the SDK V2
  • InvokeCommand of the SDK V3
Example

When analyzing the following source code:

import * as AWS from 'aws-sdk'
// Set region

function my_invoke(){
  AWS.config.update({region: 'REGION'});
  var lambda = new AWS.Lambda();
  var params = {
    FunctionName: 'mylambda', /* required */
    //...
  };

  lambda.invoke(params, function(err, data) {
    //...
  });
}

call to AWS lambda function object named mylambda is created. com.castsoftware.wbslinker links that call to lambda object to AWS Lambda Function objects having the same name: 




AWS SNS analysis

Click here to expand...

The following APIs are supported:

For SDK V2:

The publish and subscribe methods of the SNS client are supported:

import AWS from 'aws-sdk'
const snsClient = new AWS.SNS({...})
snsClient.publish(...)
snsClient.subscribe(...)

For SDK V3

The PublishCommand and SubscribeCommand (which are used with the snsClient.send method are supported);

import { SNSClient, PublishCommand, SubscribeCOmmand } from "@aws-sdk/client-sns";
const snsClient = new SNSClient({ region: REGION });
snsClient.send(new PublishCommand(params))
snsClient.send(new SubscribeCommand(params))


A Nodejs SNS Publisher object is created whenever a publication to a topic is found by the analyzer. Its name is that of the topic.

For subscriptions, a Nodejs SNS Subscriber object is created. Its name is that of the topic. Then for each supported protocol, an object is created with a callLink from the subscriber to that object. The supported protocols are the following:

protocol

object created

name of the object

emailNodejs Emailan Email   (the email addresses are not evaluated)
smsNodejs SMSan SMS   (the SMS numbers are not evaluated)
http/httpsNodejs Post Servicethe url (evaluated from the endpoint)
sqsNodejs AWS Simple Queue Service Publisherthe name of the queue (evaluated from the endpoint)
lambdaNodejs Call to AWS Lambda Functionthe name of the lambda function (evaluated from the endpoint)

What results can you expect?

When analyzing the following source code:

import {CreateTopicCommand, SNSClient, SubscribeCommand, PublishCommand } from "@aws-sdk/client-sns";

const REGION = "REGION"; //e.g. "us-east-1"
// Create SNS service object.
const snsClient = new SNSClient({ region: REGION });

function my_subscribe(protocol, topic_arn, endpoint){
  const params = {
    Protocol: protocol,
    TopicArn: topic_arn, //TOPIC_ARN
    Endpoint: endpoint, 
  };
  const data = await snsClient.send(new SubscribeCommand(params));
};

function subcribe_to_foo_topic(){
   const topic_arn = 'arn:aws:sns:us-east-2:123456789012:foo_topic';
   my_subscribe("email", topic_arn, "EMAIL_ADDRESS") 
   my_subscribe("sms", topic_arn, "007")
   my_subscribe("lambda", topic_arn, "fooarn:function:lambda_name:v2")
   my_subscribe("sqs", topic_arn, "https://sqs.us-east-2.amazonaws.com/123456789012/foo_queue")

   my_subscribe("http", topic_arn, "http://foourl")
}


function publish_to_foo_topic(){
  const params = {
      Message: "MESSAGE_TEXT", // MESSAGE_TEXT
      TopicArn: 'arn:aws:sns:us-east-2:123456789012:foo_topic'
  };
  const data = await snsClient.send(new PublishCommand(params));
}

you can view the results in the normal manner (for example via CAST Enlighten):

AWS S3 analysis

Click here to expand...

Links

Link Type

Methods from SDK V2 s3client

import {AWS} from 'aws-sdk'
const s3client = new AWS.S3()

Methods from SDK V3 s3client

import {S3} from '@aws-sdk/client-s3'
const s3client = new S3()

Commands from SDK V3

imported from '@aws-sdk/client-s3'

No Link
  • createBucket

  • CreateBucketCommand
callLink
  • createMultipartUpload

  • createPresignedPost

  • abortMultipartUpload

  • completeMultipartUpload

  • deleteBucketAnalyticsConfiguration

  • deleteBucketCors

  • deleteBucketEncryption

  • deleteBucketInventoryConfiguration

  • deleteBucketLifecycle

  • deleteBucketMetricsConfiguration

  • deleteBucketPolicy

  • deleteBucketReplication

  • deleteBucketTagging

  • deleteBucketWebsite

  • deleteObjectTagging

  • deletePublicAccessBlock

  • getBucketAccelerateConfiguration

  • getBucketAcl

  • getBucketAnalyticsConfiguration

  • getBucketCors

  • getBucketEncryption

  • getBucketInventoryConfiguration

  • getBucketLifecycle

  • getBucketLifecycleConfiguration

  • getBucketLocation

  • getBucketLogging

  • getBucketMetricsConfiguration

  • getBucketNotification

  • getBucketNotificationConfiguration

  • getBucketPolicy

  • getBucketPolicyStatus

  • getBucketReplication

  • getBucketTagging

  • getBucketVersioning

  • getBucketWebsite

  • getObjectAcl

  • getObjectLegalHold

  • getObjectLockConfiguration

  • getObjectRetention

  • getObjectTagging

  • getPublicAccessBlock

  • getSignedUrl

  • listBuckets
  • listBucketAnalyticsConfigurations

  • listBucketInventoryConfigurations

  • listBucketMetricsConfigurations

  • listMultipartUploads

  • listObjectVersions

  • listParts

  • putBucketLogging
  • putBucketAnalyticsConfiguration
  • putBucketLifecycleConfiguration

  • putBucketMetricsConfiguration

  • putBucketNotification

  • putBucketNotificationConfiguration

  • putBucketPolicy

  • putBucketReplication

  • putBucketRequestPayment

  • putBucketTagging

  • putBucketVersioning

  • putObjectAcl

  • putObjectLegalHold

  • putObjectLockConfiguration

  • putObjectRetention

  • putObjectTagging

  • putPublicAccessBlock

  • putBucketAccelerateConfiguration

  • putBucketAcl

  • putBucketCors

  • putBucketEncryption

  • putBucketInventoryConfiguration

  • putBucketLifecycle

  • putBucketLogging
  • upload

  • uploadPart

  • uploadPartCopy

  • abortMultipartUpload
  • completeMultipartUpload
  • copyObject
  • createBucket
  • createMultipartUpload
  • deleteBucket
  • deleteBucketAnalyticsConfiguration
  • deleteBucketCors
  • deleteBucketEncryption
  • deleteBucketIntelligentTieringConfiguration
  • deleteBucketInventoryConfiguration
  • deleteBucketLifecycle
  • deleteBucketMetricsConfiguration
  • deleteBucketOwnershipControls
  • deleteBucketPolicy
  • deleteBucketReplication
  • deleteBucketTagging
  • deleteBucketWebsite
  • deleteObjectTagging
  • deletePublicAccessBlock
  • destroy
  • getBucketAccelerateConfiguration
  • getBucketAcl
  • getBucketAnalyticsConfiguration
  • getBucketCors
  • getBucketEncryption
  • getBucketIntelligentTieringConfiguration
  • getBucketInventoryConfiguration
  • getBucketLifecycleConfiguration
  • getBucketLocation
  • getBucketLogging
  • getBucketMetricsConfiguration
  • getBucketNotificationConfiguration
  • getBucketOwnershipControls
  • getBucketPolicy
  • getBucketPolicyStatus
  • getBucketReplication
  • getBucketRequestPayment
  • getBucketTagging
  • getBucketVersioning
  • getBucketWebsite
  • getObjectAcl
  • getObjectLegalHold
  • getObjectLockConfiguration
  • getObjectRetention
  • getObjectTagging
  • getPublicAccessBlock
  • headBucket
  • headObject
  • listBucketAnalyticsConfigurations
  • listBucketIntelligentTieringConfigurations
  • listBucketInventoryConfigurations
  • listBucketMetricsConfigurations
  • listBuckets
  • listMultipartUploads
  • listObjectVersions
  • listParts
  • putBucketAccelerateConfiguration
  • putBucketAcl
  • putBucketCors
  • putBucketEncryption
  • putBucketIntelligentTieringConfiguration
  • putBucketInventoryConfiguration
  • putBucketLifecycleConfiguration
  • putBucketLogging
  • putBucketMetricsConfiguration
  • putBucketNotificationConfiguration
  • putBucketOwnershipControls
  • putBucketPolicy
  • putBucketReplication
  • putBucketRequestPayment
  • putBucketTagging
  • putBucketVersioning
  • putBucketWebsite
  • putObjectAcl
  • putObjectLegalHold
  • putObjectLockConfiguration
  • putObjectRetention
  • putObjectTagging
  • putPublicAccessBlock
  • restoreObject
  • send
  • uploadPart
  • uploadPartCopy
  • writeGetObjectResponse
  • AbortMultipartUploadCommand
  • CompleteMultipartUploadCommand
  • CreateMultipartUploadCommand
  • DeleteBucketAnalyticsConfigurationCommand
  • DeleteBucketCorsCommand
  • DeleteBucketEncryptionCommand
  • DeleteBucketIntelligentTieringConfigurationCommand
  • DeleteBucketInventoryConfigurationCommand
  • DeleteBucketLifecycleCommand
  • DeleteBucketMetricsConfigurationCommand
  • DeleteBucketOwnershipControlsCommand
  • DeleteBucketPolicyCommand
  • DeleteBucketReplicationCommand
  • DeleteBucketTaggingCommand
  • GetBucketAccelerateConfigurationCommand
  • GetBucketAclCommand
  • DeleteBucketWebsiteCommand
  • DeleteObjectTaggingCommand
  • DeletePublicAccessBlockCommand
  • GetBucketAnalyticsConfigurationCommand
  • GetBucketCorsCommand
  • GetBucketEncryptionCommand
  • GetBucketIntelligentTieringConfigurationCommand
  • GetBucketInventoryConfigurationCommand
  • GetBucketLifecycleConfigurationCommand
  • GetBucketLocationCommand
  • GetBucketLoggingCommand
  • GetBucketMetricsConfigurationCommand
  • GetBucketNotificationConfigurationCommand
  • GetBucketOwnershipControlsCommand
  • GetBucketPolicyCommand
  • GetBucketPolicyStatusCommand
  • GetBucketReplicationCommand
  • GetBucketRequestPaymentCommand
  • GetBucketTaggingCommand
  • GetBucketVersioningCommand
  • GetBucketWebsiteCommand
  • GetObjectAclCommand
  • GetObjectLegalHoldCommand
  • GetObjectLockConfigurationCommand
  • GetObjectRetentionCommand
  • GetObjectTaggingCommand
  • GetPublicAccessBlockCommand
  • HeadBucketCommand
  • HeadObjectCommand
  • ListBucketAnalyticsConfigurationsCommand
  • ListBucketIntelligentTieringConfigurationsCommand
  • ListBucketInventoryConfigurationsCommand
  • ListBucketMetricsConfigurationsCommand
  • ListMultipartUploadsCommand
  • ListObjectVersionsCommand
  • ListPartsCommand
  • PutBucketAccelerateConfigurationCommand
  • PutBucketAclCommand
  • PutBucketAnalyticsConfigurationCommand
  • PutBucketCorsCommand
  • PutBucketEncryptionCommand
  • PutBucketIntelligentTieringConfigurationCommand
  • PutBucketInventoryConfigurationCommand
  • PutBucketLifecycleConfigurationCommand
  • PutBucketLoggingCommand
  • PutBucketMetricsConfigurationCommand
  • PutBucketNotificationConfigurationCommand
  • PutBucketOwnershipControlsCommand
  • PutBucketPolicyCommand
  • PutBucketReplicationCommand
  • PutBucketRequestPaymentCommand
  • PutBucketTaggingCommand
  • PutBucketVersioningCommand
  • PutBucketWebsiteCommand
  • PutObjectAclCommand
  • PutObjectLegalHoldCommand
  • PutObjectLockConfigurationCommand
  • PutObjectRetentionCommand
  • PutObjectTaggingCommand
  • PutPublicAccessBlockCommand
  • UploadPartCommand
  • UploadPartCopyCommand
  • WriteGetObjectResponseCommand
useInsertLink
  • putObject
  • copyObject
  • putObject
  • copyObject
  • RestoreObjectCommand
  • PutObjectCommand
  • CopyObjectCommand
useDeleteLink
  • deleteBucket
  • deleteObject

  • deleteObjects

  • deleteBucket
  • deleteObject

  • deleteObjects

  • DeleteBucketCommand
  • DeleteObjectCommand
  • DeleteObjectsCommand
useSelectLink
  • getObject
  • getObjectTorrent
  • listObjects

  • listObjectsV2

  • copyObject
  • getObject
  • getObjectTorrent
  • listObjects
  • listObjectsV2
  • copyObject
  • GetObjectCommand
  • ListObjectsCommand
  • ListObjectsV2Command
  • SelectObjectContentCommand
  • GetObjectTorrentCommand
  • CopyObjectCommand
useUpdateLink
  • putBucketAnalyticsConfiguration
  • putBucketAnalyticsConfiguration
  • RestoreObjectCommand
  • PutObjectCommand
  • CopyObjectCommand

Code samples

This code will create an S3 Bucket named "MyBucket"  and a useInsert link to that bucket

foo.ts
// Load the AWS SDK for Node.js
import * as AWS from 'aws-sdk'
// Set the region 
AWS.config.update({region: 'REGION'});

// Create S3 service object
s3 = new AWS.S3({apiVersion: '2006-03-01'});

// Create the parameters for calling createBucket
var bucketParams = {
  Bucket : "MyBucket",
  ACL : 'public-read'
};

// call S3 to create the bucket
s3.createBucket(bucketParams, function(err, data) {
  if (err) {
    console.log("Error", err);
  } else {
    console.log("Success", data.Location);
  }
});

params = {
	// ...
    Bucket: "MyBucket"
};
s3.putObject(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log(data);           // successful response
});

What results can you expect?

Once the analysis/snapshot generation has completed, you can view the results in the normal manner (for example via CAST Enlighten):

Analysis of the code sample


AWS SQS analysis

Click here to expand...
Supported apis

Methods from SDK V2 sqs client

Commands from SDK V3

imported from '@aws-sdk/client-sqs'

Publish
  • sendMessage

  • sendMessageBatch
  • SendMessageCommand
Receive
  • receiveMessage
  • ReceiveMessageCommand
Support for SDK

This code will publish a message into the "SQS_QUEUE_URL" queue:

import * as AWS from "aws-sdk";
AWS.config.update({ region: 'REGION' });

const sqs = new AWS.SQS({apiVersion: '2012-11-05'});

const queueUrl = "SQS_QUEUE_URL"

const params = {
	MessageBody: "This is a message",
    QueueUrl: queueUrl,
    MaxNumberOfMessages: 1,
    VisibilityTimeout: 0,
};
class Foo {
  sendMessage(){
	sqs.sendMessage(params, function (err, data) {
    	if (err) {
        	console.log("Error", err);
    	} else {
       	 console.log("Success", data.MessageId);
    	}
	});
 }
}

This code will receive a message from the queue "SQS_QUEUE_URL"

import * as AWS from "aws-sdk";
AWS.config.update({ region: 'REGION' });

const sqs = new AWS.SQS({apiVersion: '2012-11-05'});

const queueUrl = "SQS_QUEUE_URL"

const params = {
    QueueUrl: queueUrl,
    MaxNumberOfMessages: 1,
    VisibilityTimeout: 0,
};

export class SqsReciver {
    constructor() {
        this.reciver();
    }
    private reciver(): void {
        sqs.receiveMessage(params, (err, data) => {
	// do something
        });
    }
}
What results can you expect?

Once the analysis/snapshot generation has been completed, you can view the results in the standard manner (for example via CAST Enlighten):

Click to enlarge

When the evaluation of the queue name fails, a Node.js AWS SQS Unknown Publisher (or Receiver) will be created.

Support for AWS Dynamodb

See DynamoDB support for Node.js source code - TypeScript

Support for AWS XRay

Click here to expand...

aws-xray encapsulates AWS methods calls in order to provide status and load status. However, the encapsulation did not allow the extension to provide objects and links. With the support of AWS XRay starting in 2.6.0-beta4, these objects and links will be created.

Code samples

This code will encapsulate AWS SDK then create a dynamoDB instance, and a Table instance.

import AWSXRay from 'aws-xray-sdk-core'
import AWS from 'aws-sdk'
const AWS = AWSXRay.captureAWS(AWS) // Encapsulate AWS SDK
const DDB = new AWS.DynamoDB({ apiVersion: "2012-10-08" }) // use AWS as usual
const { v1: uuidv1 } = require('uuid');
 
// environment variables
const { TABLE_NAME, ENDPOINT_OVERRIDE, REGION } = process.env
const options = { region: REGION }
AWS.config.update({ region: REGION })
 
if (ENDPOINT_OVERRIDE !== "") {
    options.endpoint = ENDPOINT_OVERRIDE
}
 
const docClient = new AWS.DynamoDB.DocumentClient(options)
// response helper
const response = (statusCode, body, additionalHeaders) => ({
    statusCode,
    body: JSON.stringify(body),
    headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', ...additionalHeaders },
})
 

 
function addRecord(event) {
 
    let usernameField = {
        "cognito-username": getCognitoUsername(event)
    }
 
    // auto generated date fields
    let d = new Date()
    let dISO = d.toISOString()
    let auto_fields = {
        "id": uuidv1(),
        "creation_date": dISO,
        "lastupdate_date": dISO
    }
 
    //merge the json objects
    let item_body = {...usernameField, ...auto_fields, ...JSON.parse(event.body) }
 
    console.log(item_body);
     
    //final params to DynamoDB
    const params = {
        TableName: TABLE_NAME,
        Item: item_body
    }
 
    return docClient.put(params)
}
 

What results can you expect?

Once the analysis/snapshot generation has been completed, you can view the results with your favorite tool (for example via CAST Enlighten):

Click to enlarge

Analysis of the code sample

Known limitations for AWS support

  • The use of AWS.SQS with promises is not supported. For instance, no link would be created between the receiver and the handler function defined in .then() call in the following source code: 

    this.sqs.receiveMessage(params).promise().then( () => {})
  • If the queueName is set using the createQueue API, the evaluation of the queue name will fail.
  • Use of access points is not supported

SQL Database Access

This extension supports some libraries offering access to SQL databases. The SQL frameworks analysis is based on the evaluation of the first argument of the "query()" and "execute()" method calls. The first argument is evaluated and if it corresponds to an SQL query, a CAST_TS_Query object is created. In the case where the first argument does not correspond to a SQL query, we evaluate the second argument if is exists. Text only and parameterized SQL queries are supported. This heuristic allows us to support a large number of SQL database frameworks.

More about PostgreSQL "pg" framework analysis

Click here to expand...

In the following code: 

var pg = require("pg");
var conString = "pg://operator:CastAIP@localhost:2280/postgres";
var client = null;

function getTables(schema, cbTables) {
    "use strict";
    client = new pg.Client(conString);
    client.connect();
    var queryTables = client.query("SELECT table_name FROM information_schema.tables WHERE table_schema='" + 
                      schema + "' ORDER BY 	table_name");

    queryTables.on("row", function (row, result) {
        result.addRow(row);
    });
    queryTables.on("end", function (result) {
        var tables = [];
        for (i = 0; i < result.rows.length; i += 1) {
            tables.push(result.rows[i].table_name);
        }
        client.end();
        cbTables(tables);
    });
};

In this example, a TypeScript query object is created and a callLink between the getTables method and that query is added. The sql analyzer can then link that query with the corresponding table if the table exists. In the present case, this extension creates a useSelect link to the table 'tables':

More about MySQL framework analysis

Click here to expand...

In the following code: 

var connection = require('my_connection');
var router = express.Router();
var connection = require('my_connection');

router.get('/', function(req, res, next) {
	function getMostUsedApps() {
		var getmostusedapps = "SELECT a.created_by,a.name,a.category_id,t.app_id as id,COUNT(t.app_id) 
                               AS  total,a.serviceUrl,a.contractId," + "c.name as catname,p.company_name 
                               FROM track_ussd t "+ "RIGHT JOIN apps a ON t.app_id = a.id INNER JOIN categories c" + 
                               " ON a.category_id = c.id INNER JOIN profiles p ON a.created_by = p.user_id WHERE 
                               t.msisdn = '"+msisdn+"' AND a.status = 'ACTIVATE'" + "GROUP BY t.app_id ORDER BY total DESC LIMIT 3";
		
		connection.query(getmostusedapps, function(err_getmostusedapps, rows_getmostusedapps, fields_getmostusedapps) {
			render(rows_getmostusedapps);
		});
	};
});

In this example, a TypeScript query object is created and a callLink between the getMostUsedApps method and that query is added. The sql analyzer can then link that query with the corresponding table if the table exists. In the present case, this extension creates a useSelect link to the tables 'track_ussd', 'categories', 'apps':

More about MS SQL framework analysis

Click here to expand...

In the following code: 

var sql = require('mssql');

app.delete('/rest/todos/:todo_id', function doDelete(req, res) {
    'use strict';
    var id = req.params.todo_id,
        query = 'DELETE FROM TODO WHERE ID=\'' + id + '\'';
    new sql.Request().query(query, function (error) {
        if (error) {
            console.log('delete', error);
            res.status(404).send('Error when clearing completed TODOs.');
            return;
        }
        res.end();
    });
});

In this example, a TypeScript query object is created and a callLink between the anonymous function and that query is added. The sql analyzer can then link that query with the corresponding table if the table exists. In the present case, this extension creates a useDelete link to the table 'TODO':

More about MS SQL "node-sqlserver" framework analysis

Click here to expand...

In the following code: 

var sql = require('node-sqlserver');

var connStr = "Driver={SQL Server Native Client 11.0};Server=myySqlDb,1433;Database=DB;UID=Henry;PWD=cat;";
var query = "SELECT * FROM GAData WHERE TestID = 17";

sql.open(connStr, function doSelect(err,conn){
    if(err){
        return console.error("Could not connect to sql: ", err);
    }

	conn.queryRaw("SELECT TOP 10 FirstName, LastName FROM authors", function (err, results) {
        if (err) {
            console.log("Error running query!");
            return;
        }
        for (var i = 0; i < results.rows.length; i++) {
            console.log("FirstName: " + results.rows[i][0] + " LastName: " + results.rows[i][1]);
        }
    });
});

In this example, a TypeScript query object is created and a callLink between the anonymous function and that query is added. The sql analyzer can then link that query with the corresponding table if the table exists. In the present case, this extension creates a useSelect link to the table 'authors':

More about OracleDB framework analysis

Click here to expand...

In the following code: 

var oracledb = require('oracledb');
 
oracledb.getConnection(
  {
    user          : "hr",
    password      : "welcome",
    connectString : "localhost/XE"
  },
  function doSelect(err, connection)
  {
    if (err) { console.error(err); return; }
    connection.execute(
      "SELECT department_id, department_name "
    + "FROM titles "
    + "WHERE department_id < 70 "
    + "ORDER BY department_id",
      function(err, result)
      {
        if (err) { console.error(err); return; }
        console.log(result.rows);
      });
  });
};

In this example, a TypeScript query object is created and a callLink between the anonymous function and that query is added. The sql analyzer can then link that query with the corresponding table if the table exists. In the present case, this extension creates a useSelect link to the table 'titles':

Links

Analysis of the TypeScript application will result in the following links:

  • callLink: Created when a method or a function is called. These links connect TypeScript Method and TypeScript Function elements between them.
  • inheritLink: Represents direct inheritance between TypeScript Class and TypeScript Interface objects.

Rules

The following rules are shipped with this extension:

The rule "Avoid too many copy-pasted artifacts" depends on com.castsoftware.html5 extension. It will be activated automatically for TypeScript source code when using a version of com.castsoftware.html5 >= 2.0.15-funcrel.

Limitations

  • Limitations for support of the following frameworks are given in their own section:
  • Calls between JavaScript and TypeScript source codes are not supported.
  • The use of setters and getters is not supported.
  • Passing the URL strings directly (or string variables referring to URLs) as arguments to web-service calls is supported for many use cases. However, passing them through http.RequestOptions (containing metadata) is work in progress.
  • String concatenations using the operator '+' inside loops do not raise violations currently.
  • The cyclomatic complexity number might appear underestimated in callables containing loops with complex conditional expressions.
  • A single production environment file is supported (see corresponding section above).
  • The use of bind method is not supported and would lead to missing callLinks.
  • The use of Object.freeze method is not supported.
  • React Without JSX is not supported.
  • The spread operator "..." is not supported.