I really like the structure of a NX workspace, and that lead me to start using it when building a new CLI project.
I started with creating a @nrwl/node:application but i currently is having some issues making it executable.
I believe this is not a problem with NX itself, but i can't add a shebang #!/usr/bin/env node in the main.ts file since the tsc transpiler will complain.
Module parse failed: Unexpected character '#' (1:0) File was processed
with these loaders: * ./node_modules/ts-loader/index.js
I have added the "bin": {"cli": "main.js"} property in my package.json file but if i run the main.js file without the shebang i will get this error:
line 1: syntax error near unexpected token `('
C:\Users\*\AppData\Roaming\npm/node_modules/*/dist/apps/*/main.js: line 1: `(function(e, a) { for(var i in a) e[i] = a[i]; }(exports, /******/ (function(modules) { // webpackBootstrap
Is there any smart way of solving this?
npx create-nx-workspace@latest cli-workspace --preset empty --cli nx --nx-cloud falsecd cli-workspacenpm install -D @nrwl/nodenx generate @nrwl/node:application my-cli#!/usr/bin/env node to the top of the main.ts filenpm startI've had the same problem. I could solve this by using the @nx-extend/gcp-functions:build builder to build the application, then I've created a custom executor to install the application as a CLI tool.
import { ExecutorContext } from '@nrwl/devkit';
import { exec } from 'child_process';
import { promisify } from 'util';
import * as fs from 'fs';
export interface NodeInstallOptions {
buildPath: string;
appName: string;
}
export default async function nodeInstallExecutor(
options: NodeInstallOptions,
context: ExecutorContext
) {
let success = true;
const mainPath = `${options.buildPath}/main.js`;
console.log('Building library...');
await runBashLine(success, `nx build ${options.appName}`);
console.log('Adding shebang line to main.js...');
const file = fs.readFileSync(mainPath, 'utf8');
const first_line = file.split("\n")[0];
if (first_line !== '#!/usr/bin/env node') {
var data = "#!/usr/bin/env node\n\n";
data += fs.readFileSync(mainPath, 'utf8');
fs.writeFileSync(mainPath, data);
}
console.log("Packing library...")
await runBashLine(success, `cd ${options.buildPath}; npm pack`);
console.log('Installing library...');
await runBashLine(success, `npm install -g ${options.buildPath}/*.tgz`);
return { success };
}
async function runBashLine(success: boolean, line: string) {
const { stdout, stderr } = await promisify(exec)(line);
console.log(stdout);
console.error(stderr);
success = success && !stderr;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With