Skip to content

Repository files navigation

bg-js-cli

This package provides a framework for writing javascript commands that are distributed via OS package managers such as deb and rpm. It is a part of the bg-core family of application development. When using the bg-dev tools to create and maintain custom software packages for yourself or for an organization, this package adds extensions that provide several cmd.script.javascript.* asset types and the corresponding templates and installers.

The main features are...

  • getting node/electron to accept an extensionless filename as an input module

  • command interpreters wrappers over node and electron for use in shebang lines that do not rely on passing optional argument (which is not universally supportted)
    • #!/usr/bin/env node-cli : for writing js script commands that use only text terminal input and output
    • #!/usr/bin/env node-guiMain : for commands that execute in the electron main process which can spawn gui windows and dialog boxes as well as reading a writing to the text terminal
    • #!/usr/bin/env node-guiWin : for commands that execute in an electron BrowserWindow renderer process to display a user interface in a desktop winodow.

  • script will be parsed as ES modules by default (i.e. using import instead of require())

  • each command interpreter wrapper has a corresponding version with -cjs appended that will change the default to parse the input script as cjs sysntax. (i.e. using require() instead of import)

ES Modules and Cjs Modules:

The command interpreter wrapper commands over node and electron flip the typical default for javascript modules so that the input module will be treated as the more modern ES module syntax by default.

To write a javascript command using cjs syntax (i.e. using require() instead of import ... from ), use one of the command interpreters that ends in -cjs.

As of the initial release of this package (circa 2022-12), electron is at version 22 and has very little support for ES modules so the third party module 'esm' is used to load the main and renderer input modules. The esm parser is lax compared to a compliant ES module parser which means scripts written using one of the gui* commands will be allowed to use require() as well as import and start using globals without declaring them with const,var or let. There may be other differences as well. A future release will use the the native parser so you should try to write compliant code and not rely on the 'extra' features that the esm parser allows.

Dependencies:

This distribution system creates folder structures during development and when installed on a target host that do not rely on NODE_PATHS.

A javascript command should be written in a package project created and maintained by the bg-dev tool and package. A package project can contain 0 or more commands written in javascript and they can coexist with commands written in other languages and any other asset type present in the package project.

compatible with npm/yarn dependency management

The package project folder will have a package.json that contains an export for each javascript command and a node_modules/ folder that contains the union of all dependencies used by any javascript command in the project.

The development time project structure is compatible with using npm/yarn and other packaging tools to manage and install dependencies. node_modules/ is git ignored and dependencies are tracked and managed in package.json/package-lock.json the same as in the familiar nodejs/electron workflow.

option for git submodules

In addition to the nodejs workflows, it is also possible to clone a dependency's git repo under node_modules/ and use git submodules to track the version that your project uses. Both methods can be used side by side in the same project. The build tools ensure that the node_modules/ and package*.json are consistent and up-to-date when the project is built into a deb or rpm package for publishing. Using git submodules is convenient when you are a contributor to the dependent project also. This allows you to make changes in both projects and then manage the publishing workflow in tandem with the tools found in 'bg-dev sdlc ...'.

option for deb/rpm package dependencies

Another addition to the nodejs conventions is that your package project can declare dependencies on other deb/rpm packages that contain one or more globally installed js modules. These dependencies are resolved with symlinks in your project's node_module/ folder. The symlinks are mangaed by the bg-dev tool at development time and the package installer scripts when installed on a target machine. The strategy for versioning with deb/rpm package is that your package must be compatible with the version of the dependent package that is contained in the same repository that you publish your package to. Note that this allows different versions of the dependent js module to be installed by different packages. Your project will get the version installed by the package that you declare the denpendency on. Pacakage dependencies are maintained in pkgControl/{deb,rpm}Control.

dependencies are bundled with your package

Unlike npm/yarn, the dependencies in node_modules/ become part of the packaged project and will be installed on the target along with your code when the package is installed. A folder will be created in the target for your package at '/usr/lib/node_modules/' (or similar in other OS). In that folder will be the package.json, package-lock.json, the node_modules/ folder and each of your javascript command files from your project. Symlinks are created for each command from /usr/bin/ pointing to the corresponding command '/usr/lib/node_modules//.(mjs|cjs)'. Symlinks in the node_modules/ subfolder will be created to the /usr/lib/nodes_module/ of any packages your project is dependent on that contain jsmodules.

native js module support coming...

Native js modules are not initially supported as depedencies. This is because the bg-dev tools so far do not build architecture specific (i.e. compiled) packages. A future release will support them and at that time, if you include a native module, your package will need to be built and distributed for each architecture you plan to support.

Shebang Aliases:

Shebang lines are the first line in a script command file that tells the OS which script language interpreter to use. When a script command is executed by a user, the OS will execute the executable named in the shebang line passing it the full path to the script command file.

Since not all OS support passing additional arguments to the interpreter in the shebang line, aliases are provided that call this node-cli with the options needed to define how to interpret the script file.

The shebang line in a script must be the very first line in the file with no leading whitespace.

|--------------------------------|-------------------------------|
| #!/usr/bin/env node-cli | calls node-cli |
| #!/usr/bin/env node-guiMain | calls node-cli --guiMain |
| #!/usr/bin/env node-guiWin | calls node-cli --guiWin |
| #!/usr/bin/env node-guiHtml | calls node-cli --guiHtml |
| #!/usr/bin/env node-cli-cjs | calls node-cli --cjs |
| #!/usr/bin/env node-guiMain-cjs | calls node-cli --cjs --guiMain |
| #!/usr/bin/env node-guiWin-cjs | calls node-cli --cjs --guiWin |

Security Model:

The internet browser security model draws the defensive line between the user's machine and the code running in the browser. In other words browser security is based on allowing untrusted second and third party code run on the user's machine. That is a major motivation of electron separating applications into the main process which is on the user's side and the window renderer process which must be assumed to be hostile to the user.

The security model of the bg-core family of software is that software delivered through trusted repositories should have a fiduciary responsibility to act on behalf of the user, putting the user's right to privacy above the software author's interest to capitalize the user's use of the application.

When this framework runs a node-guiWin script, the BrowserWindow that the script runs in has the internet browser security features turned off. This makes the BrowserWindow very inappropriate for running 2nd and 3rd party arbitrary code found at arbitrary internet URL's. The assumption of this library is the only locally installed scripts should be allowed to run in these windows.

As this library matures, I will look for ways wrap electron APIs to enforce this alternate security policy and will try to implement a system where both security models are avaiables and each will fully enforce the model that it implements. For example in the local desktop window security model it should not be possible for the script to change the document.location to a URL that is not content installed on the host in a system folder.

The script author can still use this framework to launch and control traditional BrowserWindows that work on the traditional internet browser security model. By using the node-guiMain interpreter a script will run in the electron main process where it can launch BrowserWindows with the security features set for what ever purpose the window will serve.

About

This demonstrates proposed changes to node, electron and atom command lines

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages