74 lines · 2.3 KB · JavaScript
RawDownload
import { getPropertyName, isIdentifier, unwrapExpression } from "../utils.js"; const promiseRejectMessage =  "Do not use Promise.reject(). Model async failures with Effect.fail or Effect.tryPromise. Skill: wrdn-effect-typed-errors.";const rejectCallbackMessage =  "Do not call Promise executor reject(). Model async failures with Effect.fail or Effect.tryPromise. Skill: wrdn-effect-typed-errors."; const isPromiseReject = (node) => {  const expression = unwrapExpression(node);  return (    expression?.type === "MemberExpression" &&    isIdentifier(unwrapExpression(expression.object), "Promise") &&    getPropertyName(expression.property) === "reject"  );}; const isPromiseConstructor = (node) =>  node?.type === "NewExpression" && isIdentifier(unwrapExpression(node.callee), "Promise"); const isFunction = (node) =>  node?.type === "ArrowFunctionExpression" ||  node?.type === "FunctionExpression" ||  node?.type === "FunctionDeclaration"; export default {  meta: {    type: "problem",    docs: {      description: "Disallow Promise rejection APIs.",    },  },  create(context) {    const promiseExecutors = new WeakSet();    const rejectNames = [];     const enterFunction = (node) => {      if (!promiseExecutors.has(node)) return;      const rejectParam = node.params?.[1];      if (isIdentifier(rejectParam)) {        rejectNames.push(rejectParam.name);      } else {        rejectNames.push(undefined);      }    };     const exitFunction = (node) => {      if (promiseExecutors.has(node)) rejectNames.pop();    };     return {      NewExpression(node) {        if (!isPromiseConstructor(node)) return;        const executor = node.arguments?.[0];        if (isFunction(executor)) promiseExecutors.add(executor);      },      CallExpression(node) {        if (isPromiseReject(node.callee)) {          context.report({ node, message: promiseRejectMessage });          return;        }         if (isIdentifier(node.callee) && rejectNames.includes(node.callee.name)) {          context.report({ node, message: rejectCallbackMessage });        }      },      FunctionDeclaration: enterFunction,      "FunctionDeclaration:exit": exitFunction,      FunctionExpression: enterFunction,      "FunctionExpression:exit": exitFunction,      ArrowFunctionExpression: enterFunction,      "ArrowFunctionExpression:exit": exitFunction,    };  },};