mirror of
https://github.com/orhun/git-cliff.git
synced 2024-09-11 06:55:38 +03:00
feat(npm): add programmatic API for TypeScript (#523)
* feat: add programmatic api * fix: return the execa result from the programmatic API instead of exiting the process * feat: make it possible to customize execa when using the programmatic api * fix: fixed dev script * refactor: remove unnecessary await * chore: update lockfile and let yarn resort dependencies * style: formatting in tsup config * chore(npm): log the error in case of exe path is not found --------- Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
This commit is contained in:
parent
292723109f
commit
8b33267967
2
npm/git-cliff/.gitignore
vendored
2
npm/git-cliff/.gitignore
vendored
@ -125,7 +125,7 @@ dist
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
# yarn berry
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
|
893
npm/git-cliff/.yarn/releases/yarn-4.1.0.cjs
vendored
Executable file
893
npm/git-cliff/.yarn/releases/yarn-4.1.0.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
5
npm/git-cliff/.yarnrc.yml
Normal file
5
npm/git-cliff/.yarnrc.yml
Normal file
@ -0,0 +1,5 @@
|
||||
enableGlobalCache: true
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.1.0.cjs
|
@ -2,13 +2,32 @@
|
||||
"name": "git-cliff",
|
||||
"version": "2.1.0-rc.0",
|
||||
"description": "A highly customizable Changelog Generator that follows Conventional Commit specifications ⛰️",
|
||||
"bin": "lib/index.js",
|
||||
"type": "module",
|
||||
"main": "lib/cjs/index.d.cts",
|
||||
"module": "lib/esm/index.d.ts",
|
||||
"types": "lib/cjs/index.d.cts",
|
||||
"bin": "lib/cli/cli.js",
|
||||
"exports": {
|
||||
"./cli": {
|
||||
"import": "./lib/cli/cli.js"
|
||||
},
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./lib/esm/index.d.ts",
|
||||
"default": "./lib/esm/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./lib/cjs/index.d.cts",
|
||||
"default": "./lib/cjs/index.cjs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit",
|
||||
"typecheck": "tsc",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix",
|
||||
"build": "tsc",
|
||||
"dev": "yarn build && node lib/index.js"
|
||||
"build": "tsup",
|
||||
"dev": "yarn build && node lib/cli/cli.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -54,20 +73,24 @@
|
||||
"url": "https://github.com/orhun/git-cliff/issues"
|
||||
},
|
||||
"homepage": "https://github.com/orhun/git-cliff#readme",
|
||||
"dependencies": {
|
||||
"execa": "^8.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.18",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.0",
|
||||
"@typescript-eslint/parser": "^5.48.0",
|
||||
"eslint": "^8.31.0",
|
||||
"typescript": "^4.9.4"
|
||||
"@types/node": "^20.11.22",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
||||
"@typescript-eslint/parser": "^7.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
"tsup": "^8.0.2",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"git-cliff-linux-x64": "2.1.0-rc.0",
|
||||
"git-cliff-linux-arm64": "2.1.0-rc.0",
|
||||
"git-cliff-darwin-x64": "2.1.0-rc.0",
|
||||
"git-cliff-darwin-arm64": "2.1.0-rc.0",
|
||||
"git-cliff-windows-x64": "2.1.0-rc.0",
|
||||
"git-cliff-windows-arm64": "2.1.0-rc.0"
|
||||
"git-cliff-darwin-x64": "2.1.0-rc.0",
|
||||
"git-cliff-linux-arm64": "2.1.0-rc.0",
|
||||
"git-cliff-linux-x64": "2.1.0-rc.0",
|
||||
"git-cliff-windows-arm64": "2.1.0-rc.0",
|
||||
"git-cliff-windows-x64": "2.1.0-rc.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
@ -82,5 +105,6 @@
|
||||
"lib/*"
|
||||
],
|
||||
"root": true
|
||||
}
|
||||
},
|
||||
"packageManager": "yarn@4.1.0"
|
||||
}
|
||||
|
12
npm/git-cliff/src/cli.ts
Normal file
12
npm/git-cliff/src/cli.ts
Normal file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { runGitCliff } from "./index.js";
|
||||
|
||||
async function run() {
|
||||
const args = process.argv.slice(2);
|
||||
const processResult = await runGitCliff(args);
|
||||
|
||||
process.exit(processResult.exitCode ?? 0);
|
||||
}
|
||||
|
||||
void run();
|
33
npm/git-cliff/src/getExePath.ts
Normal file
33
npm/git-cliff/src/getExePath.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { arch as getArch, platform as getPlatform } from "os";
|
||||
|
||||
/**
|
||||
* Returns the executable path for git-cliff located inside node_modules
|
||||
* The naming convention is git-cliff-${os}-${arch}
|
||||
* If the platform is `win32` or `cygwin`, executable will include a `.exe` extension
|
||||
* @see https://nodejs.org/api/os.html#osarch
|
||||
* @see https://nodejs.org/api/os.html#osplatform
|
||||
* @example "x/xx/node_modules/git-cliff-darwin-arm64"
|
||||
*/
|
||||
export async function getExePath() {
|
||||
const platform = getPlatform();
|
||||
const arch = getArch();
|
||||
|
||||
let os = platform as string;
|
||||
let extension = "";
|
||||
|
||||
if (platform === "win32" || platform === "cygwin") {
|
||||
os = "windows";
|
||||
extension = ".exe";
|
||||
}
|
||||
|
||||
try {
|
||||
// Since the bin will be located inside `node_modules`, we can simply call import.meta.resolve
|
||||
return import.meta.resolve(
|
||||
`git-cliff-${os}-${arch}/bin/git-cliff${extension}`,
|
||||
);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Couldn't find git-cliff binary inside node_modules for ${os}-${arch} (${e})`,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,39 +1,61 @@
|
||||
#!/usr/bin/env node
|
||||
import { execa, type Options as ExecaOptions, type ExecaReturnValue, } from "execa";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { getExePath } from "./getExePath.js";
|
||||
import type { Options } from "./options.js";
|
||||
import { optionsToStringArgs } from "./optionsToStringArgs.js";
|
||||
|
||||
import { spawnSync } from "child_process"
|
||||
export type { Options } from "./options.js";
|
||||
|
||||
/**
|
||||
* Returns the executable path for git-cliff located inside node_modules
|
||||
* The naming convention is git-cliff-${os}-${arch}
|
||||
* If the platform is `win32` or `cygwin`, executable will include a `.exe` extension
|
||||
* @see https://nodejs.org/api/os.html#osarch
|
||||
* @see https://nodejs.org/api/os.html#osplatform
|
||||
* @example "x/xx/node_modules/git-cliff-darwin-arm64"
|
||||
*/
|
||||
function getExePath() {
|
||||
const arch = process.arch;
|
||||
let os = process.platform as string;
|
||||
let extension = '';
|
||||
if (['win32', 'cygwin'].includes(process.platform)) {
|
||||
os = 'windows';
|
||||
extension = '.exe';
|
||||
}
|
||||
|
||||
try {
|
||||
// Since the bin will be located inside `node_modules`, we can simply call require.resolve
|
||||
return require.resolve(`git-cliff-${os}-${arch}/bin/git-cliff${extension}`)
|
||||
} catch (e) {
|
||||
throw new Error(`Couldn't find git-cliff binary inside node_modules for ${os}-${arch}`)
|
||||
}
|
||||
}
|
||||
|
||||
* Runs `git-cliff` with the provided options as a JavaScript object.
|
||||
*
|
||||
* @param options - The options to pass to `git-cliff`.
|
||||
* These get transformed into an array strings.
|
||||
* - Values that are `true` will be passed as flags (`--flag`).
|
||||
* - Values that are `false` or `null` will be ignored.
|
||||
* - All other values will be passed as options (`--option value`).
|
||||
*
|
||||
* @param execaOptions - Options to pass to {@link execa}.
|
||||
*/
|
||||
export async function runGitCliff(options: Options, execaOptions?: ExecaOptions): Promise<ExecaReturnValue<string>>;
|
||||
/**
|
||||
* Runs `git-cliff` with args using nodejs spawn
|
||||
*/
|
||||
function runGitCliff() {
|
||||
const args = process.argv.slice(2)
|
||||
const processResult = spawnSync(getExePath(), args, { stdio: "inherit" })
|
||||
process.exit(processResult.status ?? 0)
|
||||
}
|
||||
* Runs the `git-cliff` with the provided arguments.
|
||||
*
|
||||
* @param args - The arguments to pass to `git-cliff`.
|
||||
* These should be in an array of string format.
|
||||
* Every option and their value should be its own entry in the array.
|
||||
*
|
||||
* @param execaOptions - Options to pass to {@link execa}.
|
||||
*
|
||||
* @returns A promise that resolves when the `git-cliff` has finished running.
|
||||
*
|
||||
* @example
|
||||
* Options with values
|
||||
* ```typescript
|
||||
* await runGitCliff(["--tag", "1.0.0", "--config", "github"]);
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* Boolean flags
|
||||
* ```typescript
|
||||
* await runGitCliff(["--unreleased", "--topo-order"]);
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* Combining options and flags
|
||||
* ```typescript
|
||||
* await runGitCliff(["--tag", "1.0.0", "--config", "github", "--topo-order"]);
|
||||
* ```
|
||||
*/
|
||||
export async function runGitCliff(args: string[], execaOptions?: ExecaOptions): Promise<ExecaReturnValue<string>>;
|
||||
export async function runGitCliff(argsOrOptions: Options | string[], execaOptions?: ExecaOptions): Promise<ExecaReturnValue<string>> {
|
||||
const exePath = await getExePath();
|
||||
const args = Array.isArray(argsOrOptions)
|
||||
? argsOrOptions
|
||||
: optionsToStringArgs(argsOrOptions);
|
||||
|
||||
runGitCliff()
|
||||
return execa(fileURLToPath(exePath), args, {
|
||||
stdio: "inherit",
|
||||
...execaOptions,
|
||||
});
|
||||
}
|
||||
|
29
npm/git-cliff/src/options.ts
Normal file
29
npm/git-cliff/src/options.ts
Normal file
@ -0,0 +1,29 @@
|
||||
export type Options = Partial<{
|
||||
help: boolean;
|
||||
version: boolean;
|
||||
verbose: boolean;
|
||||
init: boolean | string;
|
||||
config: string;
|
||||
workdir: string;
|
||||
repository: string;
|
||||
includePath: string;
|
||||
excludePath: string;
|
||||
withCommit: string;
|
||||
skipCommit: string;
|
||||
prepend: string;
|
||||
output: string;
|
||||
tag: string;
|
||||
bump: boolean;
|
||||
bumpedVersion: boolean;
|
||||
body: string;
|
||||
latest: boolean;
|
||||
current: boolean;
|
||||
unreleased: boolean;
|
||||
topoOrder: boolean;
|
||||
noExec: boolean;
|
||||
context: boolean;
|
||||
strip: "header" | "footer" | "all";
|
||||
sort: "oldest" | "newest";
|
||||
githubToken: string;
|
||||
githubRepo: string;
|
||||
}>;
|
26
npm/git-cliff/src/optionsToStringArgs.ts
Normal file
26
npm/git-cliff/src/optionsToStringArgs.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import type { Options } from "./options.js";
|
||||
|
||||
/**
|
||||
* Transforms a JavaScript object of options into an array
|
||||
* of strings that can be passed to {@link execa} for calling `git-cliff`
|
||||
*
|
||||
* @param options The options to transform
|
||||
* @returns The options as an array of strings
|
||||
*/
|
||||
export function optionsToStringArgs(options: Options): string[] {
|
||||
const args: string[] = [];
|
||||
|
||||
for (const [key, value] of Object.entries(options)) {
|
||||
const hyphenCaseKey = key.replace(/([A-Z])/g, "-$1").toLowerCase();
|
||||
|
||||
if (value === true) {
|
||||
args.push(`--${hyphenCaseKey}`);
|
||||
} else if (value === false || value === null) {
|
||||
continue;
|
||||
} else {
|
||||
args.push(`--${hyphenCaseKey}`, value);
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2016",
|
||||
"module": "commonjs",
|
||||
"module": "node16",
|
||||
"moduleResolution": "node16",
|
||||
"esModuleInterop": true,
|
||||
"baseUrl": "./",
|
||||
"outDir": "lib",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
"resolveJsonModule": true,
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
||||
|
36
npm/git-cliff/tsup.config.ts
Normal file
36
npm/git-cliff/tsup.config.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { defineConfig, type Options } from "tsup";
|
||||
import { dependencies } from "./package.json";
|
||||
|
||||
const baseOptions: Options = {
|
||||
clean: true,
|
||||
dts: true,
|
||||
entry: ["src/index.ts"],
|
||||
minify: false,
|
||||
external: Object.keys(dependencies),
|
||||
sourcemap: true,
|
||||
target: "es2020",
|
||||
tsconfig: "tsconfig.json",
|
||||
keepNames: true,
|
||||
treeshake: true,
|
||||
};
|
||||
|
||||
export default [
|
||||
defineConfig({
|
||||
...baseOptions,
|
||||
outDir: "lib/cjs",
|
||||
format: "cjs",
|
||||
}),
|
||||
defineConfig({
|
||||
...baseOptions,
|
||||
outDir: "lib/esm",
|
||||
format: "esm",
|
||||
}),
|
||||
defineConfig({
|
||||
...baseOptions,
|
||||
outDir: "lib/cli",
|
||||
entry: ["src/cli.ts"],
|
||||
dts: false,
|
||||
sourcemap: false,
|
||||
format: "esm",
|
||||
}),
|
||||
];
|
File diff suppressed because it is too large
Load Diff
@ -17,3 +17,19 @@ npm install git-cliff --save-dev
|
||||
```
|
||||
|
||||
Afterwards, you can run **git-cliff** via `npm exec git-cliff` or `npx git-cliff@latest`.
|
||||
|
||||
## Programmatic API
|
||||
|
||||
**git-cliff** also provides a fully typed programmatic API. You can use it to integrate **git-cliff** into your own tooling.
|
||||
|
||||
```typescript
|
||||
import { runGitCliff, type Options } from 'git-cliff';
|
||||
|
||||
const options: Options = {
|
||||
// ...
|
||||
};
|
||||
|
||||
runGitCliff(options);
|
||||
```
|
||||
|
||||
Under the hood this will parse the options, set up the environment and call the **git-cliff** binary for you.
|
||||
|
Loading…
Reference in New Issue
Block a user