'Typescript configure mapping for compiled import path
I have an aws amplify project which is using yarn workspaces.
My project has a lambda function and a layer. When the lambda function runs in aws it needs to import my library from the layer...
import MyLib from '/opt/nodejs/build/MyLib';
However when I run this function locally I want to import the library from my local file system
import MyLib from '/Users/sive/Documents/SWT/wake-book/amplify/backend/function/wakebookLayer/lib/nodejs/build/MyLib';
How can I tell typescript to compile an import from /opt/nodejs/build/MyLib
to the location on my local file system.
I tried using path mapping in my tsconfig.json
"baseUrl": ".",
"paths": {
"/opt/nodejs/build/MyLib": ["./amplify/backend/function/wakebookLayer/lib/nodejs/build/MyLib.d.ts"]
},
This stops vscode complaining about an unknown import, so it is being 'linked' correctly (I can cmd click my import /opt/nodejs/build/MyLib
path and I am taken to the full file system path.)
But the compiled js is still using the wrong path.
The compiled js file looks like this
const MyLib_1 = __importDefault(require("/opt/nodejs/build/MyLib"));
I would expect it to remap the import path and to look like this
const MyLib_1 = __importDefault(require("/Users/sive/Documents/SWT/wake-book/amplify/backend/function/wakebookLayer/lib/nodejs/build/MyLib"));
If I manually edit the output js to have the full file system path it works (I can run my project locally).
- Have I misunderstood how path mapping is supposed to work?
- Is there a way to get my desired behaviour?
Solution 1:[1]
It's been a year and a half since this post was first answered, and there still doesn't seem to be a widely publicized solution to this issue.
So in case anyone stumbles upon this, here's what I came up with:
I have a JAVASCRIPT (.js, not a .ts file) in all my lambda function handler directories whose single responsibility is to import the layer, at run time, from the appropriate path (at either the '/opt/nodejs' path or the local path on my computer). It does so using a try/catch mechanism, which I know is a sort of anti-pattern, but it works well for this scenario.
try{
module.exports = require("/opt/nodejs/index")
} catch {
module.exports = require("../../layer/index"); // my local path
}
Then, in my handler code I import the layer with this code snippet:
import layer = require("../../layer"); // path to aforementioned file
This solution is leveraging an obscure typescript feature referred to as 'export = syntax'
https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require
It only works if the file that imports the switching layer code is a javascript (.js) file. It doesn't work if it's a typescript (.ts) file. So you'll also have to configure your tsconfig.json file with "allowJs": true
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Http417 |