Build solutions in BRIX / Server dependencies in npm packages

Server dependencies in npm packages

In BRIX On-Premises, you can add server dependencies in widget scripts. This allows you to solve some uncommon problems without writing custom microservices. Instead, you can use the rich ecosystem of npm packages when writing server scripts. For example, you can add the XLSX package to read data from Excel files using the following commands:

import * as XLSX from 'xlsx';
 
const url = await Context.data.file.getDownloadUrl();
const req = await fetch(url);
const data = await req.arrayBuffer();
 
const workbook = XLSX.read(data);
const sheets = workbook.Sheets;
const cellValue = sheets['Sheet1']['A1'].v;

начало внимание

Server dependencies in npm packages can be added only in BRIX On-Premises.

конец внимание

To create an npm package, pack the prepared node_modules folder and the package.json file into an archive called dependencies.tar.gz. For more details see:

Install Docker before starting work.

Building a package with server dependencies using a Shell script for Linux, macOS

  1. Create an empty folder on your computer. Copy the script below and save it as a file named makedeps.sh in the created folder:

rm -rf ./deps
docker run -v `pwd`:/data -w /data/deps --platform linux/amd64 --rm node:14.16.0-alpine /bin/sh -c "npm init -y && npm i $*"
docker run -v `pwd`:/data -w /data --platform linux/amd64 --rm busybox tar -zcf dependencies.tar.gz -C /data/deps node_modules package.json
rm -rf ./deps

  1. Through the developer console, find the saved file and make it executable:

$chmod 755 makedeps.sh

  1. Run the script, passing a list of npm packages as parameters. For example, for the XLSX package:

$./makedeps.sh xlsx semver

As a result of the command execution, an archive with dependencies named dependencies.tar.gz.

  1. Upload the package to the system; this can be done in the widget settings in the interface designer and in the custom module when creating an API method: add the obtained dependencies archive on the Files tab.

Packed server dependencies can be used in server script code.

Building a package with server dependencies using a PowerShell script for Windows

  1. Create an empty folder on your computer. Copy the script below and save it as a file named makedeps.ps1 in the created folder:

$ErrorActionPreference = "SilentlyContinue" #This will hide errors
Remove-Item -Recurse -Force .\deps
$ErrorActionPreference = "Continue" #Turning errors back on
docker run -v ${PWD}:/data -w /data/deps --platform linux/amd64 --rm node:14.16.0-alpine /bin/sh -c "npm init -y && npm i $args"
docker run -v ${PWD}:/data -w /data --platform linux/amd64 --rm busybox:stable tar -zcf dependencies.tar.gz -C /data/deps node_modules package.json
Remove-Item -Recurse -Force .\deps

  1. Run the script, passing a list of npm packages as parameters. For example, for the XLSX package:

$./makedeps.ps1 xlsx semver

As a result of the command execution, an archive with dependencies named dependencies.tar.gz.

  1. Upload the package to the system; this can be done in the widget settings in the interface designer and in the custom module when creating an API method: add the obtained dependencies archive on the Files tab.

Packed server dependencies can be used in server script code.

Module connection features

Pay attention to some features of importing components when connecting modules.

In custom scripts

can be imported:

cannot be imported:

  • modules from package.json (dependencies section).
  • transitive dependencies;
  • host modules (in relation to worker);
  • built-in node.js modules (fs, path, tty, etc.).

In external modules imported into the script

can be imported:

cannot be imported:

  • any other modules present in the dependencies directory.;
  • built-in node.js modules (fs, path, tty, etc.).
  • host modules (in relation to worker).

TypeScript compilation on the server is performed with the following tsconfig parameters:

{
    allowJs: true,
    checkJs: false,
    declaration: false,
    module: "commonjs",
    moduleResolution: "node",
    noImplicitAny: true,
    strictNullChecks: true,
    stripInternal: true,
    skipDefaultLibCheck: true,
    target: "ES2017",
    typeRoots: ['node_modules/@types', 'node_modules'],
    lib: ['es2016']
}

Note that not all npm packages work with these parameters without modifications. You may need to wrap them in a thin layer compatible with CommonJS or AMD.

Supported JavaScript module systems

As server-side dependencies, you can use modules based on two JavaScript module systems: CommonJS and UMD (Universal Module Definition).

Module import examples

Using the CommonJS module as an example, let's look at how to import it. Let's say a module contains one function and one constant:

function add(a, b) {
return a + b;
}
 
const name = 'noname'
 
module.exports = {
add,
name
}

You can import such module in three ways:

// 1 named import
 
import { add, name } from 'module_name';
 
async function test(): Promise<void> {
   Context.data.res = add(1, 3);
   Context.data.text = name;
}
 
// 2 namespace import
 
import * as m from 'module_name';
 
async function test(): Promise<void> {
   Context.data.res = m.add(1, 3);
   Context.data.text = m.name;
}
 
// 3 alias import
 
import { add as plus } from 'module_name';
 
async function test(): Promise<void> {
   Context.data.res = plus(1, 3);
}

Module documentation frequently includes examples with require for import. Instead of using require, you can use namespace import as shown in the second example above:

var m = require('module_name');
m.example();
 
...
 
import * as m from 'module_name';
m.example();