mirror of
https://github.com/actualbudget/actual.git
synced 2026-04-28 18:40:34 -05:00
Refactor no-cross-package-imports rule to remove hard-banned imports and streamline relative path resolution. Update tests to reflect changes in error messaging for imports not declared in dependencies.
This commit is contained in:
@@ -92,13 +92,13 @@ void runClassic(
|
||||
},
|
||||
],
|
||||
},
|
||||
// @actual-app/core cannot import @actual-app/web (hard ban)
|
||||
// @actual-app/core cannot import @actual-app/web (not in its deps)
|
||||
{
|
||||
code: 'import { Component } from "@actual-app/web";',
|
||||
filename: 'packages/loot-core/src/server/main.ts',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'hardBannedImport',
|
||||
messageId: 'noCrossPackageImport',
|
||||
data: {
|
||||
currentPackage: '@actual-app/core',
|
||||
importedPackage: '@actual-app/web',
|
||||
@@ -176,13 +176,13 @@ void runClassic(
|
||||
},
|
||||
],
|
||||
},
|
||||
// export * from @actual-app/web in loot-core triggers hard ban
|
||||
// export * from @actual-app/web in loot-core is blocked (not in its deps)
|
||||
{
|
||||
code: 'export * from "@actual-app/web";',
|
||||
filename: 'packages/loot-core/src/index.ts',
|
||||
errors: [
|
||||
{
|
||||
messageId: 'hardBannedImport',
|
||||
messageId: 'noCrossPackageImport',
|
||||
data: {
|
||||
currentPackage: '@actual-app/core',
|
||||
importedPackage: '@actual-app/web',
|
||||
|
||||
@@ -41,7 +41,7 @@ function toMonorepoRelative(filename) {
|
||||
return normalized.substring(normalizedRoot.length + 1);
|
||||
}
|
||||
|
||||
// For relative paths, try to resolve against monorepo root
|
||||
// Resolve relative paths (e.g. from test harnesses) against monorepo root
|
||||
const resolved = path.resolve(monoRoot, filename).replace(/\\/g, '/');
|
||||
if (resolved.startsWith(normalizedRoot + '/')) {
|
||||
return resolved.substring(normalizedRoot.length + 1);
|
||||
@@ -156,8 +156,6 @@ module.exports = {
|
||||
messages: {
|
||||
noCrossPackageImport:
|
||||
'Package "{{currentPackage}}" does not declare a dependency on "{{importedPackage}}". Add it to dependencies in package.json or remove the import.',
|
||||
hardBannedImport:
|
||||
'Package "{{currentPackage}}" must never import "{{importedPackage}}". This boundary is enforced unconditionally to keep {{currentPackage}} platform-agnostic.',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -168,79 +166,32 @@ module.exports = {
|
||||
// Not inside a recognized package — nothing to check
|
||||
if (!pkgInfo) return {};
|
||||
|
||||
// Hard-banned import pairs: these are always forbidden regardless of package.json deps
|
||||
const HARD_BANS = [{ from: '@actual-app/core', to: '@actual-app/web' }];
|
||||
|
||||
function isHardBanned(currentPkg, targetPkg) {
|
||||
return HARD_BANS.some(
|
||||
ban => ban.from === currentPkg && ban.to === targetPkg,
|
||||
);
|
||||
}
|
||||
|
||||
function checkImportSource(node, source) {
|
||||
if (typeof source !== 'string') return;
|
||||
|
||||
// Check @actual-app/* imports
|
||||
const importedPackage = extractActualPackageName(source);
|
||||
if (importedPackage) {
|
||||
if (importedPackage === pkgInfo.name) return;
|
||||
|
||||
if (isHardBanned(pkgInfo.name, importedPackage)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'hardBannedImport',
|
||||
data: {
|
||||
currentPackage: pkgInfo.name,
|
||||
importedPackage,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pkgInfo.allowedDeps.has(importedPackage)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noCrossPackageImport',
|
||||
data: {
|
||||
currentPackage: pkgInfo.name,
|
||||
importedPackage,
|
||||
},
|
||||
});
|
||||
}
|
||||
return;
|
||||
// Resolve the target package name from either @actual-app/* or relative imports
|
||||
let importedPackage = extractActualPackageName(source);
|
||||
if (!importedPackage) {
|
||||
const targetDir = resolveRelativeCrossPackage(
|
||||
source,
|
||||
filename,
|
||||
pkgInfo.dirName,
|
||||
);
|
||||
if (!targetDir) return;
|
||||
importedPackage = getPackageNameForDir(targetDir) || targetDir;
|
||||
}
|
||||
|
||||
// Check relative imports that cross package boundaries
|
||||
const targetDir = resolveRelativeCrossPackage(
|
||||
source,
|
||||
filename,
|
||||
pkgInfo.dirName,
|
||||
);
|
||||
if (targetDir) {
|
||||
const targetPkgName = getPackageNameForDir(targetDir) || targetDir;
|
||||
if (importedPackage === pkgInfo.name) return;
|
||||
|
||||
if (isHardBanned(pkgInfo.name, targetPkgName)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'hardBannedImport',
|
||||
data: {
|
||||
currentPackage: pkgInfo.name,
|
||||
importedPackage: targetPkgName,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pkgInfo.allowedDeps.has(targetPkgName)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noCrossPackageImport',
|
||||
data: {
|
||||
currentPackage: pkgInfo.name,
|
||||
importedPackage: targetPkgName,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (!pkgInfo.allowedDeps.has(importedPackage)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'noCrossPackageImport',
|
||||
data: {
|
||||
currentPackage: pkgInfo.name,
|
||||
importedPackage,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user