jovotech / jovo-framework

🔈 The React for Voice and Chat: Build Apps for Alexa, Messenger, Instagram, the Web, and more
https://www.jovo.tech
Apache License 2.0
1.68k stars 309 forks source link

Dependency Injection not working in AWS Lambda #1472

Open jrglg opened 1 year ago

jrglg commented 1 year ago

I'm submitting a...

Expected Behavior

Dependency injection system should work in Lambda as it's working in Express.

Current Behavior

A simple Jovo project (starting template) with an injected service doesn't work in Lambda because injections are undefined.

I attach an example project to test this out.

Error Log

2022-11-30T09:48:53.263Z a6ce2161-b66a-42c9-b211-0fb192650c92 ERROR TypeError: Cannot read property 'testMethod' of undefined at j_.handler [as LAUNCH] (/var/src/components/GlobalComponent.ts:26:22) at Vk.executeHandler (/var/node_modules/@jovotech/framework/src/ComponentTreeNode.ts:90:40) at processTicksAndRejections (internal/process/task_queues.js:95:5) at Hj.handle (/var/node_modules/@jovotech/framework/src/plugins/HandlerPlugin.ts:58:5) at vj.run (/var/node_modules/@jovotech/framework/src/Middleware.ts:24:7) at Aj.run (/var/node_modules/@jovotech/framework/src/MiddlewareCollection.ts:108:7) at mk.handle (/var/node_modules/@jovotech/framework/src/App.ts:246:7) at Runtime.handler (/var/src/server.lambda.ts:16:3)

Your Environment

Example project

test.zip

jrglg commented 1 year ago

Palle gave me a quick fix: https://jovodevs.slack.com/archives/C01RH3TMPFF/p1669802643125869?thread_ts=1669802525.160419&cid=C01RH3TMPFF

I had a Gitlab pipeline, so to keep it working I deleted the bundle script,

then I added a few more config to be like Jovo build npm script:

const {build} = require("esbuild");
const {esbuildDecorators} = require("@anatine/esbuild-decorators");

build({
    platform: "node",
    target: "node14",
    bundle: true,
    sourcemap: true,
    minify: true,
    keepNames: true,
    format: "cjs",
    tsconfig: __dirname + '/tsconfig.json',
    entryPoints: [`${__dirname}/${process.argv[2]}`], // the name of the ts stage app file
    outfile: "bundle/index.js",
    external: [
        "aws-sdk",
        "@oclif/:*",
        "@jovotech/cli*",
        "@alexa/*",
        "mongodb-client-encryption", // if you use MongoDb Jovo integration
    ],
    plugins: [
        esbuildDecorators({
            tsconfig: __dirname + "/tsconfig.json",
            cwd: process.cwd(),
        })
    ]
});

and changed the deploy:STAGE script to node build.js src/app.STAGE.ts.

So far it's working.

rmtuckerphx commented 1 year ago

Hey @palle-k can you explain what the issue is and why the fix works?

palle-k commented 1 year ago

@rmtuckerphx esbuild doesn't emit decorator metadata like the normal typescript compiler does. This metadata includes data like the arguments that a constructor has, including the argument types.

The dependency injection system requires this metadata to instantiate classes. That's also the reason why types need to be annotated with @Component or @Injectable for dependency injection to work.

This build script restores decorator metadata by compiling files that include decorators with the normal typescript compiler instead of esbuild.

rmtuckerphx commented 1 year ago

This is how I updated package.json:

    "bundle": "node build.js",

Here is the code for build.js:

const { build } = require('esbuild');
const { esbuildDecorators } = require('@anatine/esbuild-decorators');

const entryPoint = process.argv[2];
console.log('build entry point:', entryPoint);

build({
  bundle: true,
  outfile: 'bundle/index.js',
  sourcemap: true,
  minify: true,
  keepNames: true,
  platform: 'node',
  target: 'node14',
  format: 'cjs',
  external: ['aws-sdk', '@oclif/*', '@jovotech/cli*'],
  entryPoints: [entryPoint], 
  plugins: [
    esbuildDecorators({
      tsconfig: './tsconfig.json',
      cwd: process.cwd(),
    }),
  ],
});

@aswetlow You should add to docs for projects built with Dependency Injection that are deployed to Lambda

sadlowskij commented 5 months ago

Even though this is kind of an old issue, I just wanted to add, that I recently found out, that for our projects the esbuildDecorators leads to sourcemaps being out of sync. If I am working with this plugin, and throw an error, the line number of the ts file in the error message will be incorrect. Commenting the plugin out will fix this issue. Did any of you who are using this experience something similar?