2025-01-03 09:14:18 +03:00

77 lines
2.0 KiB
JavaScript

function getSubscribeNodeFrom(observableNode) {
return observableNode.callee;
}
function isSubscribedObservable(observableNode) {
try {
return observableNode.callee.property.name === 'subscribe';
} catch {
return false;
}
}
function getPipeNodeOf(subscribeNode) {
try {
var pipeNodeRef = subscribeNode.object.callee;
if (pipeNodeRef.property.name !== 'pipe') throw new Error();
return pipeNodeRef;
} catch {
return undefined;
}
}
function getOperatorsFor(pipeNode) {
return pipeNode.parent.arguments;
}
function isReleaseOperator(operatorNode) {
return operatorNode.callee.name === 'takeUntil' || operatorNode.callee.name === 'untilDestroyed';
}
module.exports = {
meta: {
type: "problem",
docs: {
description: "Check every rx.js subscription handling with release operator.",
},
fixable: "code",
schema: []
},
create: function (context) {
return {
CallExpression(node) {
if (isSubscribedObservable(node)) {
const subscribeNode = getSubscribeNodeFrom(node);
const pipeNode = getPipeNodeOf(subscribeNode);
if (pipeNode) {
const operators = getOperatorsFor(pipeNode);
if (operators.length) {
if (!isReleaseOperator(operators[operators.length - 1])) {
context.report({
node,
message: 'Last operator in pipe should release subscription. Example: `subj$.pipe(operator1(), operator2(), takeUntil(destroy$))`'
});
}
} else {
context.report({
node,
message: 'Pipe associated with subscribed observable should have release operator such `takeUntil(destroy$)`'
});
}
} else {
context.report({
node,
message: 'Subscriptions Should be piped with release operator'
});
}
}
}
};
}
};