dependency-cruiser
dependency-cruiser copied to clipboard
Question: Resolving typescript source files imported from outside specified package
Summary
I'm using the dependency-cruiser JS API to recursively construct a list of all source files referenced by an entry point. When this typescript entry point or any of its dependencies imports some module, my IDE is able to jump to the typescript where that is defined, and in essence, I want to do the same thing using dependency-cruiser
.
The following code (abstracted)
import { cruise, ICruiseOptions, ICruiseResult } from "dependency-cruiser";
// other imports
async function cruiseDirs() {
const ARRAY_OF_FILES_AND_DIRS_TO_CRUISE: string[] = [
getAbsolutePathFromUniverseRelativePath(
"redash/managed_redash/packages/app/src/open-marketplace/OpenMarketplace.tsx"
),
];
try {
const cruiseOptions: ICruiseOptions = {
exclude: {
path: ".*node_modules",
},
};
const cruiseResult = cruise(
ARRAY_OF_FILES_AND_DIRS_TO_CRUISE,
cruiseOptions
);
console.log(JSON.stringify(cruiseResult.output, null, 2));
} catch (error) {
console.error(error);
}
}
cruiseDirs();
prints out generally what I want. Within redash/managed_redash/packages/app
, dependency-cruiser
knows how to resolve dependencies to typescript code. In the above example, the OpenMarketplace.tsx
file that we start from has these two imports
import { Marketplace } from '@databricks/dbsql/src/app/pages/marketplace/Marketplace';
import { MarketplaceFilterContextProvider } from '@databricks/dbsql/src/app/pages/marketplace/filter/contexts/MarketplaceFilterProvider';
And dependency-cruiser resolves these to ../../../redash/managed_redash/packages/app/src/app/pages/marketplace/filter/contexts/MarketplaceFilterProvider.tsx
and ../../../redash/managed_redash/packages/app/src/app/pages/marketplace/Marketplace.tsx
which is what i want!
However, when we import from directories outside of the one specified initially, we run into some issues with resolving imports to their source typescript. Take the following output from dependency-cruiser
{
"source": "../../../redash/managed_redash/packages/app/src/app/services/location.ts",
"dependencies": [
{
"module": "@databricks/web-shared/mfe-services",
"moduleSystem": "es6",
"dynamic": false,
"exoticallyRequired": false,
"resolved": "../../../js/packages/web-shared/mfe-services.mjs",
"coreModule": false,
"followable": true,
"couldNotResolve": false,
"dependencyTypes": [
"npm"
],
"matchesDoNotFollow": false,
"circular": false,
"valid": true
},
@databricks/web-shared/mfe-services
resolves to some js, which I don’t expect (maybe naively), since the IDE somehow recognizes in
import { isRpcSupported } from '@databricks/web-shared/mfe-services';
That isRpcSupported
resolves to a specific typescript file.
Further, we also get some unresolved paths:
{
"source": "@databricks/persona-nav",
"followable": false,
"coreModule": false,
"couldNotResolve": true,
"matchesDoNotFollow": false,
"dependencyTypes": [
"unknown"
],
"dependencies": [],
"dependents": [
"../../../redash/managed_redash/packages/app/src/app/pages/marketplace/hooks/useMarketplaceTracking.tsx",
"../../../redash/managed_redash/packages/app/src/app/extensions/edge/components/ApplicationLayout/ApplicationWrapper.tsx",
… CUT FOR BREVITY
These other packages (@databricks/web-shared/…
, @databricks/persona-nav
) are included in the monorepo root package.json
as part of a yarn workspace. Here's the abbreviated structure of our monorepo
universe
├── package.json <- specifies the packages in the yarn workspace
├── redash
│ └── managed_redash
│ ├── packages
│ │ ├── app
│ │ │ └── package.json
├── js
│ ├── packages
│ │ ├── persona-nav
│ │ │ └── package.json
│ │ ├── web-shared
│ │ │ └── package.json
My question: What do I need to add to dependency-cruiser’s options in order to resolve these js files to their typescript source? I tried to require("dependency-cruiser/config-utl/extract-ts-config");
, and add redash/managed_redash/packages/app/tsconfig.json
to cruise
as a parameter, but the output did not change. Here’s the tsconfig of the package that has the entry point that I’m trying to cruise.
{
"extends": "../../tsconfig.base.json", // <-- this does not include any path aliases
"compilerOptions": {
"target": "es2019",
"lib": ["dom", "dom.iterable", "esnext", "esnext.intl", "es2017.intl", "es2018.intl"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsxImportSource": "@emotion/react",
"baseUrl": "./",
"paths": {
"@databricks/dbsql/*": ["./*"]
},
"types": ["node", "jest", "@testing-library/jest-dom", "ace", "@databricks/config-webpack/env"],
"incremental": true
},
"include": ["next-env.d.ts", "globals.d.ts", "emotion.d.ts", "recoil/testing.d.ts", "**/*.ts", "**/*.tsx"]
}
Context
For more context, I'm building a script that takes some set of typescript entry points and checks if their usages (or any of their dependencies' usages) of a certain library are correct (based on some other validation) with respect to that entry point.
Environment
- Version used: [email protected]
- Node version: 20.13.1
- Operating System and version: Mac OS Sonoma 14.4.1