Forge typescript support - absolute path imports (compilerOption rootDir)

I have rewritten Forge app to typescript and I was trying to set up absolute path imports (from root) with tsconfig

    "compilerOptions": {
        "rootDir": "./src",
        "baseUrl": "./src",

I get no errors or warnings in editor but once i run forge deploy, it crashes on invalid import so I was wondering if anyone of you tried it and if there is some workaround or it is impossible and would be Feature Request on atlassian

1 Like


If you don’t mind, what are you trying to achieve by enabling absolute path imports? The deploy step shouldn’t produce a broken application without complaining, but I’m curious to see if there’s a use case for this.

Can you please show a (cut down) example of a failing app?

Hi, thanks for the response. So basically, I have file structure for customfield type Forge App like this:

β”œβ”€β”€ package.json
β”œβ”€β”€ src
β”‚    β”œβ”€β”€ api
|    |    β”œβ”€β”€ issue.ts (function getAllJqlResults)
|    |    β”œβ”€β”€ customfield.ts
|    |    └── logger.ts
β”‚    β”œβ”€β”€ index.tsx
β”‚    └── screens
|          └── edit
|                └── App.tsx (<-- trying to import getAllJqlResults)
└── tsconfig.json

and when I am in ./src/screens/edit/App.tsx I wanted to be able to import my api calls from ./src/api module (with previously mentioned tsconfig import should looks like this)

import getAllJqlResults from "api/issue"

but that throws this error (running: forge deploy --verbose)

β„Ή Packaging app files

Error: Bundling failed: Module not found: Error: Can't resolve 'api/issue' in '/Users/____/csas/code/forge/jira-customfields/src/screens/edit'

Error: Bundling failed: Module not found: Error: Can't resolve 'api/issue' in '/Users/____/csas/code/forge/jira-customfields/src/screens/edit'
    at RuntimeBundler.bundle (/opt/homebrew/lib/node_modules/@forge/cli/out/deploy/packager/runtime-bundler.js:27:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async AppPackager.package (/opt/homebrew/lib/node_modules/@forge/cli/out/deploy/packager/packager.js:16:31)
    at async PackageUploadDeployCommand.execute (/opt/homebrew/lib/node_modules/@forge/cli/out/deploy/package-upload-deploy.js:14:76)
    at async CommandLineUI.displayProgress (/opt/homebrew/lib/node_modules/@forge/cli/node_modules/@forge/cli-shared/out/ui/command-line-ui.js:46:28)
    at async DeployView.reportDeploymentProgress (/opt/homebrew/lib/node_modules/@forge/cli/out/command-line/view/deploy-view.js:54:24)
    at async (/opt/homebrew/lib/node_modules/@forge/cli/out/command-line/controller/deploy-controller.js:129:27)
    at async Command.actionProcessor (/opt/homebrew/lib/node_modules/@forge/cli/out/command-line/command.js:93:32)
    at async Promise.all (index 0)
    at async Command.parse (/opt/homebrew/lib/node_modules/@forge/cli/out/command-line/command.js:196:13)
    at async main (/opt/homebrew/lib/node_modules/@forge/cli/out/command-line/index.js:57:5)

but when I change it to relative import

import getAllJqlResults from "../../api/issue"

then there are no problems

Thanks for the explanation!

Your Forge application runs in a special runtime environment Atlassian maintains. Forge CLI uses Webpack internally to bundle your application, and unfortunately our configuration seems to be incompatible with the absolute paths configuration.

I suggest either (in order of preference):

  • Leaving the relative references in your code - this is common in JavaScript/TypeScript projects
  • Pulling some functionality into proper Node modules and referencing them in your package.json - this will let you import them per Node conventions (e.g. import { fetch } from '@forge/api')
  • Or if you aren’t satisfied with our bundling altogether, run a pre-build step to bundle your application into a single file, put that in src/index.js and use forge deploy afterwards.
1 Like