swc-command

1.0.5 • Public • Published

SWC-COMMAND

swc command cli node api banner


SWC nodejs api to run swc cli seamlessly from node. Intended for main usage with programmatic build scripts.

Many times we find ourselves needing to write a build script instead of just configuration.
For example, combining dev build with launching electron ....

Some also like that, for the flexibility of the programmatic side.

Whatever it is. This package and module is intended for this usage. It allow you to run swc-cli through a simple and concise api. Typed with typescript. Autocompletion. And the package provide 3 versions swc promise version, and the version you would mostly use. cpswc child process version , swcSync a synchronous version.

Installation

pnpm add swc-command -D
npm install swc-command -D
yarn add swc-command -D

Usage

Let's suppose you are about to build a project.

swc()

Configuration

As by the following example. The configuration take the cli arguments as camel case equiv (--out-dir => outDir).

Check the list of all arguments in the official doc

Along that we added spawnOptions prop to configure the spawn properties.

import { swc, isCompilationSuccessful } from 'swc-command'

(async () => {
  // Configuration
  const cliOptions = {
    outDir: path.join(rootDir, 'dist'),
    src: path.join(rootDir, 'src'),
    noSwcrc: true,
    spawnOptions: {
      encoding: 'utf8'
    },
    config: {
      jsc: {
        parser: {
          decorators: true,
          syntax: 'typescript',
          dynamicImport: true
        },
        externalHelpers: true,
        target: 'es5'
      },
      minify: true,
      module: {
        type: 'commonjs'
      },
      sourceMaps: true
    }
  };

  // Executing the cli
  const { data, exitCode, exitSignal } = await swc(cliOptions)

  if (isCompilationSuccessful(data.stdout)) {
    // Compilation successful
    console.log(data.stdout);
    startElectron();
  }

  // testing stdout content directly
  if (data.stdout.join('').includes('Successfully compiled:')) {
    // this is equivalent to the above. You can check in a similar manner for any specific case and cli output message.
  }
})()

With child process instance access

You can use that to print back to console. Or in cases of output-ing the compiled source to console. And you want to process the output in a stream based.

import { swc, isCompilationSuccessful } from 'swc-command'
const stdoutData: string[] = []

(async () => {
  await swc(cliOptions, (childProcess) => {
    // do something with the ChildProcess instance
    // check cpswc for an example

    childProcess.stdout.on('data', console.log)  // output to console
    childProcess.stderr.on('data', console.log) //

    childProcess.stdout.on('data', (data) => {
      console.log(data);
      // You can do whatever you want. Including printing back to the console.
    })
  })
})()

Cli Options

export type TPswcExecOptions = TExecOptions & {
  resolveEvent?: 'close' | 'exit';
  data?: {
    stdout?: boolean;
    stderr?: boolean;
  };
};

export type TExecOptions = TCommandOptions & {
  spawnOptions?: TExecSpawnOptions;
};

// TCommandOptions the cli camel case equiv args (props)

resolveEvents

resolveEvent?: 'close' | 'exit';

close or exit, default to close.

And it's used to precise at what event of the spawn process should the promise resolve. It can be the close event or the exit event. exit event happens before the close event. You can read more about that in the spawn documentation.

data

data?: {
  stdout?: boolean;
  stderr?: boolean;
};

Optional.

Default to { stdout: true, stderr: true }.

If any set to false. The according output wouldn't be included in the data prop of the result object.

const { data, exitCode, exitSignal } = await swc(cliOptions);
data.stdout // will contain stdout output as an array. Undefined if not included.
data.stderr // will contain stderr output as an array. Undefined if not included.

Spawn options

It follow Nodejs child_process spawn option type

Plus we added encoding property.

export type TExecSpawnOptions = SpawnOptions & {
  encoding?: BufferEncoding;
};

Default value for encoding is utf8. You don't need to include it.

const cliOptions = {
  // ...
  spawnOptions: {
    encoding: 'utf8'
  },
  // ...  
};

And stdio default to pipe.

swcSync() [Sync version]

const {
  output, // array // total output mixing both stdout and stderr and in an array format. Use join('') to process it as a string.
  stdout, // string or buffer (default: string)  //
  stderr, // string or buffer (default: string) // depends on encoding
  signal,
  status // exit code
} = swcSync(cliOptions);

result output is of this type:

interface SpawnSyncReturns<T> {
  pid: number;
  output: Array<T | null>;
  stdout: T;
  stderr: T;
  status: number | null;
  signal: NodeJS.Signals | null;
  error?: Error | undefined;
}

Worth noting for the cliOptions. spawnOptions is the same. And encoding default to 'utf8'. And stdio to 'pipe'.

cpswc() [child process version]

You may want to use this version if you don't want to buffer. In a wide repo. Where you compile and output to console. And you use that to process it on a stream based nature.

import { cpswc, isCompilationSuccessful } from 'swc-command'

const childProcess = cpswc(cliOptions)
  .on('close', (code, signal) => {
    // command finished executing.
    startElectron();
  })
  .on('error', (/* err */) => {
    // some unexpected execution for the spawning process
  });


childProcess.stdout?.on('data', (data) => {
  // process chunks on the go
});

childProcess.stderr?.on('data', (data) => {
  // some std error data
});

CliOptions and properties Warning

Make sure you pass an object that hold the exact supported properties of the cli.

If any one is missing from the typescript declarations. Please fill a pull request, or issue to add it.

And for flexibility reason. You can add any prop. Even if it's not in the typescript declarations. And because of that choice. We do have a requirement!

Requirement:

  • The cli options object. Should contain only the cli args props. And the one that are part of the typescript declaration.
    So if you constructed an object that contains all the necessary props for the cli execution. Furthermore you add some extra no cli props. You need to extract that out. Otherwise the command would fail. As it will take the prop as a cli arg. And that would make the cli to fail.

utils

isCompilationSuccessful

isCompilationSuccessful is a helper that take stdout output and check for Successfully compiled as per this return _stdout.join('').includes('Successfully compiled'); which is expected when the compilation is successful.

It's a helper to simplify that. If for some reason that change. Or your use case is different. That take that in mind. You may need to figure out the way you want to check with.
You can fill a pull request, or issue if that ever change in the future.

If you need something else. You can recover data.stdout and use return _stdout.join('').includes('Something to check with'); or anything else.

const { data, exitCode, exitSignal } = await swc(cliOptions)

if (isCompilationSuccessful(data.stdout)) {
  // Compilation successful
  console.log(data.stdout);
  startElectron();
}

@swc/core

You can compile files programmatically using official @swc/core package. The api only allow to manage one file at a time. And if you combine it with fast-glob. Then you'll be able to compile multiple files and using globs as well.

swc-command on the other hand. Would always give you the ability to run the cli. With all it's features from node seamlessly. And that may be more powerful. And what you would want to do most of the time.

Notes

Make sure you install swc-command@v1.0.3 at least. Because it does update @swc/core version to 1.3.11. To fix the problem bellow:

Prior v1.3.5 the cli exclude argument wasn't working.

The fix i wrote was merged on 1.3.5 of @swc/core.

For more details:

Issue: https://github.com/swc-project/swc/issues/6009

PR: https://github.com/swc-project/swc/pull/6054

Readme

Keywords

Package Sidebar

Install

npm i swc-command

Weekly Downloads

0

Version

1.0.5

License

MIT

Unpacked Size

52.8 kB

Total Files

23

Last publish

Collaborators

  • mohamed.lamine.allal