Home Manual Reference Source Test
Manual » Usage

Command Line Interface

A command line interface is provided by the atvise-scm-cli package. Please refer to it's documentation for more detailed information.

Note: The following commands are meant to be run inside already set up atvise-scm project directory. To create a new one refer to the installation manual.

Running atvise-scm tasks

Start a task by running atvise-scm [task-name] inside a atvise-scm project directory. Example:

# Run a task named "the-task-to-run"
$ atvise-scm the-task-to-run

List available tasks

To get a list of tasks available for your atvise-scm project run atvise-scm --tasks

Implementing a custom Transformer

In this document we'll guide you through the steps necessary to implement a custom Transformer. The transformer we'll implement will use Babel to transpile ES2015/ES6 JavaScript to plain ES5 JavaScript that works in all Browsers.

All code will be placed inside your project's Atviseproject.js file.

Step 1: Import the Transformer class

atvise-scm provides an abstract class (obviously called Transformer) that must be implemented by all Transformers.

To import the Transformer class into your Atviseproject.js simply add a import declaration:

Change the default import { Atviseproject } from 'atvise-scm' on top of your project file to import { Atviseproject, Transformer } from 'atvise-scm'.

By now your Atviseproject.js should look somehow like that:

import { Atviseproject, Transformer } from 'atvise-scm';

export default class MyProject extends Atviseproject {
  ...
}

Step 2: Create a Transformer subclass

Now we have to create a Transformer subclass. Add it just below the import declaration from the previous step:

// Atviseproject.js
import { Atviseproject, Transformer } from 'atvise-scm';

class BabelTransformer extends Transformer {

}

export default class MyProject extends Atviseproject {
  ...
}

Step 3: Configure atvise-scm to use your transformer

For atvise-scm to know it should use your new Transformer, add it to your project's transformers. You can do this by referencing an instance of your Transformer in your project class:

// Atviseproject.js

...

export default class MyProject extends Atviseproject {
  ...

  static get useTransformers() {
    super.useTransformers.concat(new BabelTransformer())
  }

}

Step 4: Implement Transformer.applyToTypes

If you'd run an atvise-scm task now, e.g. atvise-scm push, you'll notice an Error is thrown, saying Transformer.applyToTypes must be implemented by all subclasses. Well, let's implement it!

As stated in the documentation, Transformer.applyToTypes must be implemented to tell atvise-scm which kinds of nodes the transformer should be applied to. The NodeType class we'll import provides us with the types we can use.

For now, we only want to transpile the script code of displays:

// Atviseproject.js
import { Atviseproject, Transformer, NodeType } from 'atvise-scm';

class BabelTransformer extends Transformer {

  static get applyToTypes() {
    return {
      [NodeType.Display]: true
    };
  }

}

...

Step 5: Implement Transformer#transformFromFilesystem

The Transformer#transformFromFilesystem method is probably the most important method we'll implement. It is applied to a node.js Stream of files and responsible for transpiling the script code.

First of all, we need to install babel and a preset. Save them as development dependencies by running:

npm install --save-dev babel-core babel-preset-es2015

We'll also make use of the node.js core modules buffer and path. We do not need to install them as they come with every installation of node.js. After that, we can import these new modules in our Atviseproject.js:

// Atviseproject.js
import { Buffer } from 'buffer';
import { extname } from 'path';
import { Atviseproject, Transformer, NodeType } from 'atvise-scm';
import { transform } from 'babel-core';

...

Now we're ready to implement Transformer#transformFromFilesystem:

// Atviseproject.js
...

class BabelTransformer extends Transformer {

  static get applyToTypes() { ... }

  transformFromFilesystem(stream, file, encoding, callback) {
    // We only want to transform files ending with '.js'
    if (extname(file.relative) === '.js') {
      // Transpile code using babel
      const { code } = transform(file.contents, {
        presets: [
          'es2015',
        ],
      });

      // Create a new file containing the new code
      const result = file.clone();
      result.contents = Buffer.from(code);

      // Pass the new file to the next transformer
      callback(null, result);
    } else {
      // Ignore non-JavaScript files
      callback(null, file);
    }
  }

}

Wow! Now we can write our display scripts using the latest language features of JavaScript without any issues on older browsers. You can already test the compilation by running atvise-scm push.

Step 6: Implement Transformer#transformFromDB

As babel transpilation is a one-way process we cannot create ES2015 source code from the generated ES5 code. Therefore the only thing we can do when a file is pulled from atvise server is to display a warning. To print a pretty colored warning, we use gulp-util. Install it by running:

npm install --save-dev gulp-util

Then import it and implement Transformer#transformFromDB:

...
import { log, colors } from 'gulp-util';

class BabelTransformer extends Transformer {

  ...

  transformFromDB(stream, node, encoding, callback) {
    if (extname(node.relative) === '.js') {
      log(
        colors.yellow('Prevented overriding ES2015 source code at'),
        colors.cyan(node.relative)
      );

      // No file is passed to callback as we don't want to override the source code.
      callback();
    } else {
      // Ignore non-JavaScript files
      callback(null, node);
    }
  }

}

Now, when running atvise-scm pull you should see something like:

[15:29:13] Starting 'pull'...
[15:29:13] Prevented overriding ES2015 source code at AGENT/DISPLAYS/Default.xml/Default.js
[15:29:13] Prevented overriding ES2015 source code at AGENT/DISPLAYS/Main.xml/Main.js
[15:29:13] Found 2 nodes.
[15:29:13] Finished 'pull' after 266 ms

Result

Here is how your Atviseproject.js should look now:

// Atviseproject.js
import { Buffer } from 'buffer';
import { extname } from 'path';
import { Atviseproject, Transformer, NodeType, NodeId } from 'atvise-scm';
import { transform } from 'babel-core';
import { log, colors } from 'gulp-util';

class BabelTransformer extends Transformer {

  transformFromFilesystem(stream, file, encoding, callback) {
    // We only want to transform files ending with '.js'
    if (extname(file.relative) === '.js') {
      // Transpile code using babel
      const { code } = transform(file.contents, {
        presets: [
          'es2015',
        ],
      });

      // Create a new file containing the new code
      const result = file.clone();
      result.contents = Buffer.from(code);

      // Pass the new file to the next transformer
      callback(null, result);
    } else {
      // Ignore non-JavaScript files
      callback(null, file);
    }
  }

  transformFromDB(stream, node, encoding, callback) {
    if (extname(node.relative) === '.js') {
      log(
        colors.yellow('Prevented overriding ES2015 source code at'),
        colors.cyan(node.relative)
      );

      // No file is passed to callback as we don't want to override the source code.
      callback();
    } else {
      // Ignore non-JavaScript files
      callback(null, node);
    }
  }

  static get applyToTypes() {
    return {
      [NodeType.Display]: true
    };
  }

}

// Here comes the Atviseproject

Conclusion

We just created a ES2015-Transformer in no time. It transpiles display script code on push and prevents overriding this code on pull.

Of course there are many ways to improve the transfromer, for example:

  • Also transpile QuickDynamics and server side scripts
  • Handle options to configure how babel transpiles the source code