npm package: @kwaeri/xfmr
Description: The @kwaeri/xfmr component module of the @kwaeri application framework.
Author: Richard B. Winters
Latest version: 0.4.0

# kwaeri-xfmr

[![pipeline status](https://gitlab.com/kwaeri/cli/providers/xfmr/badges/main/pipeline.svg)](https://gitlab.com/kwaeri/cli/providers/xfmr/commits/main)  [![coverage report](https://gitlab.com/kwaeri/cli/providers/xfmr/badges/main/coverage.svg)](https://kwaeri.gitlab.io/cli/providers/xfmr/coverage/)  [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1879/badge)](https://bestpractices.coreinfrastructure.org/projects/1879)

The @kwaeri/xfmr component for the @kwaeri application platform

## TOC
* [The Implementation](#the-implementation)
* [Getting Started](#getting-started)
  * [Installation](#installation)
  * [Usage](#usage)
* [How to Contribute Code](#how-to-contribute-code)
* [Other Ways to Contribute](#other-ways-to-contribute)
  * [Bug Reports](#bug-reports)
  * [Vulnerability Reports](#vulnerability-reports)
    * [Confidential Issues](#confidential-issues)
  * [Donations](#donations)

## The Implementation

The xfmr component provides a tool that transforms the version and copyright of source files for end users of @kwaeri/cli [kue]. It is useful both in development of the kwaeri tooling and in deriving applications from kwaeri. Other source transformation utility may be provided in the future.

## Getting Started

**NOTE**

@kwaeri/xfmr is not ready for production. We've published this module for testing and development purposes. You're free to try out anything that may already be available, but please be aware that there is likely to be many aspects of the platform which are not working and/or are completely broken. As we near completion of the new platform, we'll update documentation and provide complete examples and tutorials for getting started.

### Installation

[@kwaeri/node-kit](https://www.npmjs.com/package/@kwaeri/node-kit) wraps the various components under the @kwaeri scope, and provides a single entry point to the node-kit platform for easing the process of building a kwaeri application.

[@kwaeri/cli](https://www.npmjs.com/package/@kwaeri/cli) wraps the various CLI components under the @kwaeri scope, and provides a single entry point to the user executable framework.

However, if you wish to use @kwaeri/xfmr - perform the following steps:

Install @kwaeri/xfmr either locally:

```bash
npm install --save-dev @kwaeri/xfmr
```

Or globally:

```bash
npm install -g @kwaeri/xfmr
```

### Usage

The xfmr component is leveraged for transforming the version and copyright of source files (with specific support for the version string in `package.json` files) as part of a build and publish pipeline.

To leverage the xfmr component, you can use it either:

* As a ServiceProvider of kue
* Via CLI in terminal (or similar)
* Via npm scripts
* Programatically

#### As a ServiceProvider of kue

The *command* is ***`bump`*** and the *specification* is either ***`version`*** or ***`copyright`***.

```bash
kue bump version
```

or

```bash
kue bump copyright
```

When dealing with @kwaeri/xfmr as a ServiceProvider, there are some options you can leverage. To get a list of those options, install the ServiceProvider by adding it to the list of providers in the `cli.json` file in the root of your project, and run:

```bash
kue bump --help
```

Alternatively, you can view the list of flags and options [here](#options).

For specifying the target source, as well as providing configuration, see [here](#configuration).,

#### Via Terminal-CLI

When running the Xfmr from a global installation, or from within a Node project where it is installed locally, you can forego invoking with `node` and leverage the registered binary alias: `xfmr-cli`.

```bash
xfmr-cli --bump-version --source
```

Otherwise, The binary is ***`node`*** and the target path of the binary script (as opposed to `kue`, or `xfmr-cli`) :

```bash
node ./node_modules/@kwaeri/xfmr/dist/src/bin/xfmr-cli.mjs --bump-version --project
```

When you consider how kue binaries break user commands into *command* ⇨ *specification*, the arguments passed differ slightly from when leveraging @kwaeri/xfmr as a ServiceProvider of kue.

* To bump the version, use *`--bump-version`*
  * The target must also be specified:
    * To target source file versions for files other than the `package.json`, use *`--source`*
    * To target module/project version, specifically in `package.json`, use *`--project`*
    * *NOTE* *This only specifies which preconfigured globs and keys to use from the [configuration](#configuration).*
* To bump the copyright, use *`--bump-copyright`*

Thus, to bump source file versions with default settings:

```bash
node ./node_modules/@kwaeri/xfmr/dist/src/bin/xfmr-cli.mjs --bump-version --source
```

#### As a NPM Script

To use @kwaeri/xfmr as part of a NPM script, write a script that invokes the xfmr as if you were invoking it directly from the command line ([see above](#via-terminal-cli)):

```json
{
  "scripts": {
    "bump:version": "node ./dist/src/bin/xfmr-cli.mjs --bump-version --source",
    "bump:copyright": "node ./dist/src/bin/xfmr-cli.mjs --bump-copyright --source",
  }
}
```

Then, run the npm script:

```bash
npm run bump:version
```

## Options and Configuration

* Options refer to the flags and arguments that can be passed to a CLI invocation.
* Configuration refers to the options that can and/or must be set in a file named `.xfmrc`.

### Defaults

When running `kue bump version < --source | --project >` with no additional flags or arguments, it increments the patch component of the semver. The key used is ` * @version: `.

When running `kue bump copyright` with no additional flags or arguments, it expects to find a year range, and increments the *latest* copyright year component to the current year - if it is not already the current year. The key used is ` *  Copyright © `.


### Options

The options, per specification, are as follows:

#### Version Bump

| `version` Options   | Desc                                           | Values                     |
|---------------------|------------------------------------------------|----------------------------|
| --component         | Specify the semver component to increment      | major, minor               |
| --to-version        | Specify the specific version to set            | Any valid semver           |
| --project           | Denotes to bump version in `package.json`      | None, flag-type            |
| --source            | Denotes to bump version in source files        | None, flag-type            |

With regards to the `project` and `source` flags, they can be present in the same invocation.

#### Copyright Bump

| `copyright` Option | Desc                                           | Values                         |
|--------------------|------------------------------------------------|--------------------------------|
| --type             | Specify the type of copyright bump to perform  | range (default), each, current |

With regards to copyright's *`--type`* option, it can be one of the following types:

* `range` maintains a **2020 - 2022** type of display (start to latest), and would bump the ***end*** (i.e. `2022`) component.
* `each` adds the current year, if not already present, to the current comma separated list of copyright years (i.e. **2020, 2022** ).
* `current` updates the single copyright year to the current year if it is not already the current year.

### Options Explained

In the following examples we'll assume that you've decided to create a [npm script](#as-a-npm-script) as part of a build pipeline when preparing for a new release, but with the `--source` flag removed, so as to explain the options. You can normally just place these options within the npm script itself, but we'll be explaining them by passing them to the script - hence the presence of `--`, which separates arguments passed to `npm` from arguments passed to the script itself *(see [here](https://github.com/npm/npm/pull/5518) for more information about the presence of `--`)*.

#### By Component

To increment a component of the version string, run `npm run bump:version -- --<source|project> --component <type>`. This will also reset any subsequent components to 0.

#### To a Specific Version

To set the version string to a specific version, run `npm run bump:version -- --<source|project> --to-version <version>`.

#### Of Source Files

To bump the version in ordinary source files, flag `--source`.

#### Of Package.json

To bump the version specifically in `package.json`, flag `--project`.

To be continued...

### Configuration

To allow for specifying the configuration of @kwaeri/xfmr, the module expects a `.xfmrc` file at the root of your project. Some default fallbacks are implemented, but at this time the only way to specify the target is through this configuration (See [this](#configuration-required) for more information).

For clarification, here's the most minimal configuration required:

```jsonc
{
    "source": { // Denotes source file transform options
        "match": [ "**/*.js" ],
    },
    "module": { // Denotes module metadata file (package.json) transform options
        "match": [ "package.json" ],
    }
}
```

#### Breakdown

There are two major focuses of @kwaeri/xfmr;

* Normal source files
* The project or module metadata file

With regards to the transformations that @kwaeri/xfmr currently provides, only the `bump version` transformation targets both focuses. When we leverage @kwaeri/xfmr for copyright transform - this is not applied to the package or module metadata file.

The configuration contained should minimally specify the required source file glob patterns, and any optional glob ignore patterns. You may also optionally specify any glob option supported by the [glob](https://www.npmjs.com/package/glob#options) module, destination paths for build and test runs, and alternate keys for all supported transformations.

This is why there is a `key` object for the `source` configuration, but only a `key` string for the `module` configuration.

Here's an example *comprehensive* configuration:

```jsonc
{
    "source": { // Denotes source file transform options
        "match": [
            "**/*.mts",
            "**/*.cts",
            "**/*.ts",
            "**/*.mjs",
            "**/*.cjs",
            "**/*.js"
        ],
        "globOptions": {
            "base": "./",
            "ignore": [ // Ignore patterns can be placed within globOptions
                "node_modules{/,/**}",
                "build{/,/**}",
                "dist{/,/**}",
                "test{/,/**}"
            ]
        },
        "key": {  // Copyright can only be bumped in source files, so key specification is unique here.
            "version": " * @version ",
            "copyright": " *  Copyright © "
        },
        "destination": ".",         // These destinations are the defauls, if not provided.
        "testDestination": "tests"
    },
    "module": { // Denotes module metadata file (package.json) transform options
        "match": [
            "package.json"
        ],
        "globOptions": {
            "base": "./"
        },
        "key": "\"version\": \"",
        "destination": ".",       // These destinations are the defauls, if not provided.
        "testDestination": "tests"
    }
}
```

#### Configuration Required

Ideally, we'd like to support a default implementation for when there is no configuration by allowing for the passing of paths via STDIN.

For example, one could do so as follows:

```bash
kue bump version --files "file.ext, file2.ext" --source
```

This would also allow for globbing of input sources according to the available means of doing so on a per-system basis.

On Debian Linux, for example, one could do so as follows:

```bash
echo "'$(echo -n *.mts **/*.mts *.cts **/*cts | sed "s/ /','/g")'" | cat - | <invoke xfmr>
```

Which - at the time of this writing, and on the system used - translates to:

```bash
'index.mts','dist/index.d.mts','tests/index.mts','index.cts','dist/index.d.cts','src/xfmr.cts','tests/index.cts' | ...
```

The benefits to allowing the module to work this way should be immediately discernable. How to allow this type of functionality has also already been discerned -

Below is the list of blocking items:

* `kue` needs to support reading from STDIN and packing utf8 encoded data into `NodeKitOptions` so that `Steward` can hand it off to ServiceProviders when delegating fullfilment of user commands.
* `xfmr` needs to support taking from `NodeKitOptions` when used as a ServiceProvider,
* ~~`xfmr-cli` needs to support reading from STDIN directly when used as a CLI binary itself directly.~~ Done
* ~~In all cases, `process `must be manually `unref()`'d so as to ensure that all scripts finish after all work is done.~~ done

Due to an immediate need for the functionality of this module, @kwaeri/xfmr is being initially published without said support completed. It will be added at a later time.

As such, the configuration object is required to at least minimally specify the taget source to apply desired transformations to.

**NOTE**

As mentioned earlier, the plan is to continue development of the myriad components of the node-kit platform - the service component included - and ultimately ease the process of development, maintainence, and usage of each individual component as they are decoupled from one another.


## How to Contribute Code

Our Open Source projects are always open to contribution. If you'd like to cocntribute, all we ask is that you follow the guidelines for contributions, which can be found at the [Massively Modified Wiki](https://gitlab.com/mmod/documentation/wikis/Contribute-to-Massively-Modified/Contribute-Code)

There you'll find topics such as the guidelines for contributions; step-by-step walk-throughs for getting set up, [Coding Standards](https://gitlab.com/mmod/documentation/wikis/Contribute-to-Massively-Modified/Coding-Standards), [CSS Naming Conventions](https://gitlab.com/mmod/documentation/wikis/Contribute-to-Massively-Modified/CSS-Naming-Conventions), and more.

The project also leverages Keybase for communication and alerts - outside of standard email. To join our keybase chat, run the following from terminal (assuming you have [keybase](https://www.keybase.io) installed and running):

```bash
keybase team request-access kwaeri
```

Alternatively, you could search for the team in the GUI application and request access from there.

## Other Ways to Contribute

There are other ways to contribute to the project other than with code. Consider [testing](https://gitlab.com/mmod/documentation/wikis/Contribute-to-Massively-Modified/Test-Code) the software, or in case you've found an [Bug](https://gitlab.com/mmod/documentation/wikis/Other-Ways-to-Contribute/Bug-Reports) - please report it. You can also support the project monetarly through [donations](https://gitlab.com/mmod/documentation/wikis/Contribute-to-Massively-Modified/Donations) via PayPal.

Regardless of how you'd like to contribute, you can also find in-depth information for how to do so at the [Massively Modified Wiki](https://gitlab.com/mmod/documentation/wikis/Other-Ways-to-Contribute)

### Bug Reports

To submit bug reports, request enhancements, and/or new features - please make use of the **issues** system baked-in to our source control project space at [Gitlab](https://gitlab.com/groups/kwaeri/node-kit/-/issues)

You may optionally start an issue, track, and manage it via email by sending an email to our project's [Service Desk](mailto:incoming+kwaeri-replacer-21483883-issue-@incoming.gitlab.com).

For more in-depth documentation on the process of submitting bug reports, please visit the [Massively Modified Wiki on Bug Reports](https://gitlab.com/mmod/documentation/wikis/Other-Ways-to-Contribute/Bug-Reports)

### Vulnerability Reports

Our Vulnerability Reporting process is very similar to Gitlab's. In fact, you could say its a *fork*.

To submit vulnerability reports, please email our [Security Group](mailto:security@mmod.co). We will try to acknowledge receipt of said vulnerability by the next business day, and to also provide regular updates about our progress. If you are curious about the status of your report feel free to email us again. If you wish to encrypt your disclosure email, like with gitlab - please email us to ask for our GPG Key.

Please refrain from requesting compensation for reporting vulnerabilities. We will publicly acknowledge your responsible disclosure, if you request us to do so. We will also try to make the confidential issue public after the vulnerability is announced.

You are not allowed, and will not be able, to search for vulnerabilities on Gitlab.com. As our software is open source, you may download a copy of the source and test against that.

#### Confidential Issues

When a vulnerability is discovered, we create a [confidential issue] to track it internally. Security patches will be pushed to private branches and eventually merged into a `security` branch. Security issues that are not vulnerabilites can be seen on our [public issue tracker](https://gitlab.com/groups/kwaeri/node-kit/-/issues?scope=all&utf8=✓&state=opened&label_name[]=Security).

For more in-depth information regarding vulnerability reports, confidentiality, and our practices; Please visit the [Massively Modified Wiki on Vulnerability](https://gitlab.com/mmod/documentation/wikis/Other-Ways-to-Contribute/Vulnerability-Reports)

### Donations

If you cannot contribute time or energy to neither the code base, documentation, nor community support; please consider making a monetary contribution which is extremely useful for maintaining the Massively Modified network and all the goodies offered free to the public.

[![Donate via PayPal.com](https://gitlab.com/mmod/kwaeri-user-experience/raw/master/images/mmod-donate-btn-2.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YUW4CWCAABCU2)