Skip to content

Commit

Permalink
feat: package is now ESM (#439)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Package is now ESM
  • Loading branch information
tido64 committed Mar 18, 2024
1 parent 6445d64 commit 6669b1a
Show file tree
Hide file tree
Showing 16 changed files with 384 additions and 318 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.d.ts
*.d.ts.map
*.tgz
.DS_Store
.yarn/*
Expand Down
15 changes: 9 additions & 6 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@
// LICENSE file in the root directory of this source tree.
//

const fs = require("node:fs");
const path = require("node:path");
const { parseArgs } = require("node:util");
import * as fs from "node:fs";
import * as path from "node:path";
import { fileURLToPath, URL } from "node:url";
import { parseArgs } from "node:util";
import suggest from "./src/index.js";

function printHelp() {
console.log(
[
`Usage: ${path.basename(__filename)} [options] [diff | file]`,
`Usage: ${path.basename(process.argv[1])} [options] [diff | file]`,
"",
"Submit code reviews with suggestions based on your diffs",
"",
Expand Down Expand Up @@ -66,10 +68,11 @@ const { values, positionals } = parseArgs({
if (values.help) {
printHelp();
} else if (values.version) {
const { name, version } = require("./package.json");
const p = fileURLToPath(new URL("package.json", import.meta.url));
const manifest = fs.readFileSync(p, { encoding: "utf-8" });
const { name, version } = JSON.parse(manifest);
console.log(name, version);
} else {
const suggest = require("./src/index");
if (positionals.length > 0) {
const diffOrFile = positionals[0];
const diff = fs.existsSync(diffOrFile)
Expand Down
6 changes: 4 additions & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module.exports = [
require("@eslint/js").configs.recommended,
import js from "@eslint/js";

export default [
js.configs.recommended,
{
languageOptions: {
globals: {
Expand Down
28 changes: 20 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,47 @@
},
"files": [
"cli.js",
"src/"
"src/**/*.d.ts",
"src/**/*.js"
],
"main": "src/index.js",
"bin": "cli.js",
"type": "module",
"exports": {
".": {
"default": "./src/index.js"
},
"./cli.js": {
"default": "./cli.js"
},
"./package.json": "./package.json"
},
"repository": {
"type": "git",
"url": "https://github.com/tido64/suggestion-bot.git"
},
"scripts": {
"build": "yarn clean && yarn lint && tsc",
"clean": "git clean -dfqx -- src/ test/",
"format": "prettier --write $(git ls-files '*.js' '*.json' '*.md' '*.mjs' '*.yml' ':!:.yarn/**/*.cjs')",
"lint": "eslint $(git ls-files '*.js' '*.mjs' ':!:*.config.js' ':!:.yarn/**/*.js')",
"format": "prettier --write $(git ls-files '*.js' '*.json' '*.md' '*.yml' ':!:.yarn/**/*.cjs')",
"lint": "eslint $(git ls-files '*.js' ':!:*.config.js' ':!:.yarn/**/*.js')",
"suggest": "suggestion-bot",
"test": "node --test --experimental-test-coverage $(git ls-files 'test/*.test.mjs')"
"test": "node --test --experimental-test-coverage $(git ls-files 'test/*.test.js')"
},
"dependencies": {
"@octokit/core": "^5.0",
"@octokit/plugin-rest-endpoint-methods": "^10.0",
"@octokit/core": "^6.0",
"@octokit/plugin-rest-endpoint-methods": "^11.0",
"azure-devops-node-api": "^12.0",
"parse-diff": "^0.11"
},
"devDependencies": {
"@eslint/js": "^8.56",
"@types/node": "^20.0.0",
"@rnx-kit/tsconfig": "^1.0",
"@types/node": "^20.0",
"codecov": "^3.0",
"eslint": "^8.56",
"prettier": "^3.0",
"semantic-release": "23.0.0",
"semantic-release": "^23.0",
"typescript": "^5.0"
},
"engines": {
Expand Down
26 changes: 10 additions & 16 deletions src/AzureDevOpsClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
// LICENSE file in the root directory of this source tree.
//
// @ts-check
import * as azdevapi from "azure-devops-node-api";
import { makeComments } from "./makeComments.js";

/**
* @typedef {import("azure-devops-node-api/interfaces/common/VsoBaseInterfaces").IRequestOptions} IRequestOptions
* @typedef {import("azure-devops-node-api/interfaces/GitInterfaces").GitPullRequestChange} GitPullRequestChange
* @typedef {import("azure-devops-node-api/interfaces/GitInterfaces").GitPullRequestCommentThread} GitPullRequestCommentThread
* @typedef {import("./makeComments").Comment} Comment
* @typedef {import("azure-devops-node-api/interfaces/common/VsoBaseInterfaces.js").IRequestOptions} IRequestOptions
* @typedef {import("azure-devops-node-api/interfaces/GitInterfaces.js").GitPullRequestChange} GitPullRequestChange
* @typedef {import("azure-devops-node-api/interfaces/GitInterfaces.js").GitPullRequestCommentThread} GitPullRequestCommentThread
* @typedef {import("./makeComments.js").Comment} Comment
* @typedef {{ [filePath: string]: number }} ChangeTrackingIdMap
* @typedef {(changes: ChangeTrackingIdMap, change: GitPullRequestChange) => (ChangeTrackingIdMap)} ChangeTrackingIdMapReducer
* @typedef {IRequestOptions & { azdev?: typeof import("azure-devops-node-api"); }} RequestOptions
Expand All @@ -27,11 +29,7 @@
* @param {string} authToken
* @param {RequestOptions} options
*/
function connect(
serverUrl,
authToken,
{ azdev = require("azure-devops-node-api"), ...options }
) {
function connect(serverUrl, authToken, { azdev = azdevapi, ...options }) {
const authHandler = azdev.getPersonalAccessTokenHandler(authToken);
const vsts = new azdev.WebApi(serverUrl, authHandler, options);
return vsts.connect().then(() => vsts.getGitApi());
Expand All @@ -43,7 +41,7 @@ function connect(
* @param {GitPullRequestChange} change
* @returns {string | undefined}
*/
function getItemPath(change) {
export function getItemPath(change) {
if (!change.item || !change.item.path) {
return undefined;
}
Expand Down Expand Up @@ -92,10 +90,10 @@ function transformComment(
/**
* Submits a code review with suggestions with specified diff and options.
* @param {string} diff
* @param {import("./index").Options & RequestOptions} options
* @param {import("./index.js").Options & RequestOptions} options
* @returns {Promise<unknown>}
*/
function makeReview(diff, { fail, ...options } = {}) {
export function makeReview(diff, { fail, ...options } = {}) {
const {
AZURE_PERSONAL_ACCESS_TOKEN: authToken,
BUILD_REPOSITORY_ID: repositoryId,
Expand Down Expand Up @@ -140,7 +138,6 @@ function makeReview(diff, { fail, ...options } = {}) {
);
}

const { makeComments } = require("./makeComments");
const comments = makeComments(diff);
if (comments.length === 0) {
return Promise.resolve();
Expand Down Expand Up @@ -201,6 +198,3 @@ function makeReview(diff, { fail, ...options } = {}) {
}
});
}

exports.getItemPath = getItemPath;
exports.makeReview = makeReview;
27 changes: 12 additions & 15 deletions src/GitHubClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@
// LICENSE file in the root directory of this source tree.
//
// @ts-check
import * as octokit_core from "@octokit/core";
import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";
import * as nodefs from "node:fs";
import { c } from "./helpers.js";
import { makeComments } from "./makeComments.js";

/** @typedef {import("./index").Options} Options */
/** @typedef {import("./index.js").Options} Options */

/**
* Returns the pull request number of the current build.
* @param {string} eventPath Path of the file with the complete webhook event payload.
* @param {Options} options
* @returns {number}
*/
function getPullRequestNumber(eventPath, { fs = require("fs") }) {
function getPullRequestNumber(eventPath, { fs = nodefs }) {
const e = JSON.parse(fs.readFileSync(eventPath, { encoding: "utf-8" }));
return e.pull_request.number;
}
Expand All @@ -23,11 +28,8 @@ function getPullRequestNumber(eventPath, { fs = require("fs") }) {
* Creates an Octokit instance.
* @param {Options} options
*/
function makeOctokit({ octokit, ...options }) {
const { Octokit } = octokit || require("@octokit/core");
const {
restEndpointMethods,
} = require("@octokit/plugin-rest-endpoint-methods");
function makeOctokit({ octokit = octokit_core, ...options }) {
const { Octokit } = octokit;
const RestClient = Octokit.plugin(restEndpointMethods);
return new RestClient(options);
}
Expand All @@ -38,8 +40,8 @@ function makeOctokit({ octokit, ...options }) {
* GitHub type checks the payload sent to it and fails the request if there are
* unknown fields.
*
* @param {import("./makeComments").Comment} comment
* @returns {Omit<import("./makeComments").Comment, "line_length">}
* @param {import("./makeComments.js").Comment} comment
* @returns {Omit<import("./makeComments.js").Comment, "line_length">}
*/
// eslint-disable-next-line no-unused-vars
function trimComment({ line_length, ...rest }) {
Expand All @@ -52,7 +54,7 @@ function trimComment({ line_length, ...rest }) {
* @param {Options} options
* @returns {Promise<unknown>}
*/
function makeReview(diff, { fail, message, ...options } = {}) {
export function makeReview(diff, { fail, message, ...options } = {}) {
const { GITHUB_EVENT_PATH, GITHUB_REPOSITORY, GITHUB_SHA, GITHUB_TOKEN } =
process.env;
if (!GITHUB_EVENT_PATH || !GITHUB_REPOSITORY || !GITHUB_TOKEN) {
Expand All @@ -74,14 +76,11 @@ function makeReview(diff, { fail, message, ...options } = {}) {
);
}

const { makeComments } = require("./makeComments");
const comments = makeComments(diff);
if (comments.length === 0) {
return Promise.resolve();
}

const { c } = require("./helpers");

const [owner, repo] = GITHUB_REPOSITORY.split("/");
const pullRequestNumber = getPullRequestNumber(GITHUB_EVENT_PATH, options);
const review = {
Expand Down Expand Up @@ -143,5 +142,3 @@ function makeReview(diff, { fail, message, ...options } = {}) {
});
});
}

exports.makeReview = makeReview;
10 changes: 3 additions & 7 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* @param {T} v
* @return {T}
*/
function c(v) {
export function c(v) {
return v;
}

Expand All @@ -21,7 +21,7 @@ function c(v) {
* @param {string[]} strings
* @returns {string}
*/
function concatStrings(...strings) {
export function concatStrings(...strings) {
return strings.concat("").join("\n");
}

Expand All @@ -30,7 +30,7 @@ function concatStrings(...strings) {
* @param {string} p
* @returns {string}
*/
function trimQuotes(p) {
export function trimQuotes(p) {
if (
(p.startsWith('"') && p.endsWith('"')) ||
(p.startsWith("'") && p.endsWith("'"))
Expand All @@ -39,7 +39,3 @@ function trimQuotes(p) {
}
return p;
}

exports.c = c;
exports.concatStrings = concatStrings;
exports.trimQuotes = trimQuotes;
12 changes: 5 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
/**
* Returns the appropriate client for the provided access token.
*/
function getClient() {
async function getClient() {
const { AZURE_PERSONAL_ACCESS_TOKEN, GITHUB_TOKEN } = process.env;

if (AZURE_PERSONAL_ACCESS_TOKEN) {
return require("./AzureDevOpsClient");
return import("./AzureDevOpsClient.js");
}

if (GITHUB_TOKEN) {
return require("./GitHubClient");
return import("./GitHubClient.js");
}

throw new Error("No access token was set");
Expand All @@ -40,8 +40,8 @@ function getClient() {
* @param {Options=} options
* @returns {Promise<void>}
*/
async function suggest(diff, options = {}) {
const { makeReview } = getClient();
export default async function suggest(diff, options = {}) {
const { makeReview } = await getClient();
try {
await makeReview(diff, {
...options,
Expand All @@ -53,5 +53,3 @@ async function suggest(diff, options = {}) {
process.exit(1);
}
}

module.exports = suggest;
12 changes: 5 additions & 7 deletions src/makeComments.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// LICENSE file in the root directory of this source tree.
//
// @ts-check
import parseDiff from "parse-diff";
import { trimQuotes } from "./helpers.js";

/**
* @typedef {import("parse-diff").Change} Change
Expand Down Expand Up @@ -59,7 +61,7 @@ function trimContext(changes) {
* @param {Chunk} chunk
* @returns {Comment}
*/
function makeComment(file, { changes, oldStart, oldLines }) {
export function makeComment(file, { changes, oldStart, oldLines }) {
const path = file.split("\\").join("/");

const [trimmedChanges, startContext, endContext] = trimContext(changes);
Expand Down Expand Up @@ -160,13 +162,12 @@ function makeComment(file, { changes, oldStart, oldLines }) {
* @param {string} diff
* @returns {Comment[]}
*/
function makeComments(diff) {
const files = require("parse-diff")(diff);
export function makeComments(diff) {
const files = parseDiff(diff);
if (files.length <= 0) {
return [];
}

const { trimQuotes } = require("./helpers");
return files.reduce(
/** @type {(comments: Comment[], file: File) => Comment[]} */
(comments, file) => {
Expand All @@ -182,6 +183,3 @@ function makeComments(diff) {
[]
);
}

exports.makeComment = makeComment;
exports.makeComments = makeComments;
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ import {
FIXTURE_UNIDIFF,
FIXTURE_UNIDIFF_ADO_ITERATION_CHANGES,
FIXTURE_UNIDIFF_ADO_PAYLOAD,
} from "./__fixtures__.mjs";
} from "./__fixtures__.js";

/**
* @typedef {import("azure-devops-node-api/GitApi").GitApi} GitApi
* @typedef {import("azure-devops-node-api/interfaces/GitInterfaces").GitPullRequestCommentThread} GitPullRequestCommentThread
* @typedef {import("azure-devops-node-api/interfaces/common/VsoBaseInterfaces").IRequestHandler} IRequestHandler
* @typedef {import("azure-devops-node-api/interfaces/common/VsoBaseInterfaces").IRequestOptions} IRequestOptions
* @typedef {import("azure-devops-node-api/GitApi.js").GitApi} GitApi
* @typedef {import("azure-devops-node-api/interfaces/GitInterfaces.js").GitPullRequestCommentThread} GitPullRequestCommentThread
* @typedef {import("azure-devops-node-api/interfaces/common/VsoBaseInterfaces.js").IRequestHandler} IRequestHandler
* @typedef {import("azure-devops-node-api/interfaces/common/VsoBaseInterfaces.js").IRequestOptions} IRequestOptions
* @typedef {Partial<GitApi> & {
* setAuthToken: (handler: IRequestHandler) => void;
* setServerUrl: (url: string) => void;
Expand Down Expand Up @@ -91,7 +91,7 @@ class WebApi {

/**
* @param {{}} mocks
* @returns {import("../src/AzureDevOpsClient").RequestOptions}
* @returns {import("../src/AzureDevOpsClient.js").RequestOptions}
*/
function mock(mocks) {
return {
Expand Down
Loading

0 comments on commit 6669b1a

Please sign in to comment.