Other Package Managers
+
```sh
yarn add --dev execify-cli
```
+
+```sh
+pnpm add --save-dev execify-cli
+```
+
+
## Usage
-```
+```txt
Usage
- $ execify [globs…]
+ $ execify [paths…]
Options
--package, --pkg, -p Set every binary in package.json as executable
- --fix-shebang Convert shebangs to "#!/usr/bin/env node"
- --all Set all flags
Examples
- $ execify cli.js
-
- $ execify --pkg test/fixtures/**/cli.js
-
- $ execify --fix-shebang dist/ts-cli.js
+ $ execify foo.js bar.ts baz/xyz.sh
+ ✔ Execified "foo.js"
+ ⚠ File "foo.js" is missing a shebang!
+ ℹ File "bar.ts" is already executable
+ ✖ Failed to execify "baz/xyz.sh", file not found
+
+ $ execify --pkg
+ ✔ Execified "./dist/foo.js" (foo-cli)
+ ✔ Execified "./dist/bar.js" (bar-cli)
```
-## Roadmap
-
-v0.1.0 is a minimal release. The following features were cut and will be added in the next minor version:
-
-- TypeScript import path mapping from `tsconfig.json` `paths` option
-- A flag to fix all TypeScript-related conversions
-- Logging of completed/failed files, improved error handling
-
## Related
-- [chmodx](https://github.com/johnowennixon/chmodx)
-- [ts-fix-shebang](https://github.com/johnowennixon/ts-fix-shebang)
-- [make-executable](https://github.com/bconnorwhite/make-executable)
-- [replace-in-files-cli](https://github.com/sindresorhus/replace-in-files-cli)
-- [tsconfig-replace-paths](https://github.com/jonkwheeler/tsconfig-replace-paths)
+- [chmodx](https://github.com/johnowennixon/chmodx) - A cross platform command line utility for setting the executable bits on files.
+- [make-executable](https://github.com/bconnorwhite/make-executable) - Set or remove the executable bits on a file.
diff --git a/src/cli.ts b/src/cli.ts
index b4a79c4..b381fb2 100755
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -1,57 +1,66 @@
-#!/usr/bin/env ts-node-esm
-/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
+#!/usr/bin/env node
import meow from "meow";
-import { getFiles, setExecutableBits, fixShebangs } from "./helpers.js";
+import { execify, getBinaries } from "./helpers.ts";
+import { log } from "./utils.ts";
+// dprint-ignore
const cli = meow(`
Usage
- $ execify [globs…]
+ $ execify [paths…]
Options
--package, --pkg, -p Set every binary in package.json as executable
- --fix-shebang Convert shebangs to "#!/usr/bin/env node"
- --all Set all flags
Examples
- $ execify cli.js
+ $ execify foo.js bar.ts baz/xyz.sh
+ ✔ Execified "foo.js"
+ ⚠ File "foo.js" is missing a shebang!
+ ℹ File "bar.ts" is already executable
+ ✖ Failed to execify "baz/xyz.sh", file not found
- $ execify --pkg test/fixtures/**/cli.js
-
- $ execify --fix-shebang dist/ts-cli.js
+ $ execify --pkg
+ ✔ Execified "./dist/foo.js" (foo-cli)
+ ✔ Execified "./dist/bar.js" (bar-cli)
`, {
- importMeta: import.meta,
description: false,
flags: {
help: {
- type: "boolean",
shortFlag: "h",
+ type: "boolean",
},
package: {
- type: "boolean",
- shortFlag: "p",
aliases: ["pkg"],
- },
- fixShebang: {
- type: "boolean",
- },
- all: {
+ shortFlag: "p",
type: "boolean",
},
},
+ importMeta: import.meta,
});
-const globs = cli.input;
-const { help: helpShortFlag, package: usePackageFlag, fixShebang, all: allFlags } = cli.flags;
-const usePackage = usePackageFlag || allFlags;
+const { flags: { package: usePackage }, input } = cli;
-if ((globs.length === 0 && !usePackage) || helpShortFlag) {
+if (!usePackage && input.length === 0) {
cli.showHelp(0);
}
-const filePaths = await getFiles({ globs, usePackage });
+const binaries = await getBinaries({ input, usePackage });
+const results = await execify(binaries);
+
+for (const { didExecify, error, hasShebang, name, path } of results) {
+ const nameSuffix = name ? `(${name})` : "";
+
+ if (error) {
+ log.error(`Failed to execify "${path}", ${error}`, nameSuffix);
+ continue;
+ }
-await setExecutableBits(filePaths);
+ if (didExecify) {
+ log.success(`Execified "${path}"`, nameSuffix);
+ } else {
+ log.info(`File "${path}" is already executable`, nameSuffix);
+ }
-if (fixShebang || allFlags) {
- await fixShebangs(filePaths);
+ if (!hasShebang) {
+ log.warn(`File "${path}" is missing a shebang!`, nameSuffix);
+ }
}
diff --git a/src/helpers.ts b/src/helpers.ts
index 25b416e..d40d3f2 100644
--- a/src/helpers.ts
+++ b/src/helpers.ts
@@ -1,64 +1,74 @@
-/* eslint-disable unicorn/no-array-callback-reference */
-import { promises as fs, constants as fsConstants } from "node:fs";
-import { globby } from "globby";
-import { readPackageUp } from "read-pkg-up";
-import { match, P } from "ts-pattern";
+import nodePath from "node:path";
+import process from "node:process";
+import type { OneOf } from "./types.ts";
+import { type Binary, hasShebang, log, makeExecutable, readPackageJson } from "./utils.ts";
-type GetFilesArguments = {
- globs: string[];
+type Input = {
+ input: string[];
usePackage?: boolean;
};
-export const getFiles = async ({ globs, usePackage }: GetFilesArguments): Promise