Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imports not resolving properly during runtime #329

Closed
smasilamani-cfins opened this issue Jan 4, 2021 · 3 comments
Closed

Imports not resolving properly during runtime #329

smasilamani-cfins opened this issue Jan 4, 2021 · 3 comments

Comments

@smasilamani-cfins
Copy link

Hello

We are using this package for one for our serverless typescript projects and have been facing issue with the import. During runtime none of the imports from this package are resolving and we have to do a patch to make it work, Please find below the respective code and error we get unless we run the below command after npm install. Please advise.

Command to fix :
cp -r ./node_modules/@vendia/serverless-express/src/*.js ./node_modules/@vendia/serverless-express

If we run the above command after npm install, then it works fine.

Error:

TypeError: serverless_express_1.createServer is not a function
    at bootstrapServer (/mnt/c/Repos/iq-submission-service/.webpack/service/src/webpack:/iq-submission-service/src/index.ts:38:10)
    at processTicksAndRejections (node:internal/process/task_queues:93:5)
    at handler (/mnt/c/Repos/iq-submission-service/.webpack/service/src/webpack:/iq-submission-service/src/index.ts:77:18)
    at InProcessRunner.run (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js:199:24)
    at LambdaFunction.runHandler (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/lambda/LambdaFunction.js:325:20)
    at hapiHandler (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/events/http/HttpServer.js:521:18)
    at module.exports.internals.Manager.execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/toolkit.js:45:28)
    at Object.internals.handler (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/handler.js:46:20)
    at exports.execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/handler.js:31:20)
    at Request._lifecycle (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/request.js:312:32)
    at Request._execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/request.js:221:9)
TypeError: serverless_express_1.createServer is not a function
    at bootstrapServer (/mnt/c/Repos/iq-submission-service/.webpack/service/src/webpack:/iq-submission-service/src/index.ts:38:10)
    at processTicksAndRejections (node:internal/process/task_queues:93:5)
    at handler (/mnt/c/Repos/iq-submission-service/.webpack/service/src/webpack:/iq-submission-service/src/index.ts:77:18)
    at InProcessRunner.run (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js:199:24)
    at LambdaFunction.runHandler (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/lambda/LambdaFunction.js:325:20)
    at hapiHandler (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/events/http/HttpServer.js:521:18)
    at module.exports.internals.Manager.execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/toolkit.js:45:28)
    at Object.internals.handler (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/handler.js:46:20)
    at exports.execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/handler.js:31:20)
    at Request._lifecycle (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/request.js:312:32)
    at Request._execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/request.js:221:9)
offline: Failure: serverless_express_1.createServer is not a function
TypeError: serverless_express_1.createServer is not a function
    at bootstrapServer (/mnt/c/Repos/iq-submission-service/.webpack/service/src/webpack:/iq-submission-service/src/index.ts:38:10)
    at processTicksAndRejections (node:internal/process/task_queues:93:5)
    at handler (/mnt/c/Repos/iq-submission-service/.webpack/service/src/webpack:/iq-submission-service/src/index.ts:77:18)
    at InProcessRunner.run (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js:199:24)
    at LambdaFunction.runHandler (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/lambda/LambdaFunction.js:325:20)
    at hapiHandler (/mnt/c/Repos/iq-submission-service/node_modules/serverless-offline/dist/events/http/HttpServer.js:521:18)
    at module.exports.internals.Manager.execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/toolkit.js:45:28)
    at Object.internals.handler (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/handler.js:46:20)
    at exports.execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/handler.js:31:20)
    at Request._lifecycle (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/request.js:312:32)
    at Request._execute (/mnt/c/Repos/iq-submission-service/node_modules/@hapi/hapi/lib/request.js:221:9)

Webpack:

const path = require('path');
const slsw = require('serverless-webpack');
const TsConfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const entries = {};
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const HappyPack = require('happypack');

Object.keys(slsw.lib.entries).forEach((key) => (entries[key] = ['./source-map-install.js', slsw.lib.entries[key]]));

module.exports = {
	mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
	entry: entries,
	devtool: 'source-map',
	optimization: {
		minimizer: [
			new TerserPlugin({
				terserOptions: {
					mangle: true,
					keep_classnames: true,
					sourceMap: true
				},
				parallel: true
			})
		]
	},
	plugins: [
		new ForkTsCheckerWebpackPlugin({ typescript: { memoryLimit: 4096 } }),
		new HappyPack({
			id: 'ts',
			threads: 10,
			loaders: [
				{
					path: 'ts-loader',
					query: { happyPackMode: true }
				}
			]
		})
	],
	resolve: {
		plugins: [
			new TsConfigPathsPlugin({
				configFile: './tsconfig.json'
			})
		],
		extensions: ['.js', '.jsx', '.json', '.ts', '.tsx']
	},
	output: {
		libraryTarget: 'commonjs',
		path: path.join(__dirname, '.webpack'),
		filename: '[name].js'
	},
	target: 'node',
	module: {
		rules: [
			// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
			{
				test: /\.ts|\.tsx$/,
				loader: 'ts-loader',
				exclude: [/node_modules/],
				options: {
					// disable type checker - we will use it in fork plugin
					transpileOnly: true
				}
				// include: __dirname
			}
		]
	},
	externals: [
		'oracledb',
		'mongodb',
		'mysql',
		'pg',
		'pg-native',
		'pg-query-stream',
		'redis',
		'sqlite3',
		'mssql',
		'mysql2',
		'@sap/hana-client',
		'hdb-pool',
		'typeorm-aurora-data-api-driver',
		'better-sqlite3',
		'react-native-sqlite-storage',
		'sql.js',
		'grpc',
		'kafkajs',
		'mqtt',
		'nats',
		'amqplib',
		'amqp-connection-manager',
		'fastify-swagger'
	],
	ignoreWarnings: [
		// This is optional, but it hides noisey warnings
		{ module: /node_modules\/*/, message: /Critical dependency: the request of a dependency is an expression/ },
		(warning) => false
	]
};

Code: (only the interested part)

import { Handler } from 'aws-lambda';
import Express from 'express';
import { Server } from 'http';

import { INestApplication } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';
import { DSServerConstants } from '@shared/models/server.constants';
import { createServer, proxy } from '@vendia/serverless-express';

import { bootstrap } from './main';

let cachedServer: Server;

const binaryMimeTypes: string[] = [
	'application/javascript',
	'application/octet-stream',
	'application/xml',
	'font/eot',
	'font/opentype',
	'font/otf',
	'image/jpeg',
	'image/png',
	'image/svg+xml',
	'text/comma-separated-values',
	'text/css',
	'text/html',
	'text/javascript',
	'text/plain',
	'text/text',
	'text/xml'
];

const bootstrapServer: () => Promise<Server> = async () => {
	try {
		const expressApp: any = Express();
		const expAdapter: ExpressAdapter = new ExpressAdapter(expressApp);
		const app: INestApplication = await bootstrap(expAdapter);
		return createServer(app.getHttpAdapter().getInstance(), null, binaryMimeTypes);
	} catch (error) {
		console.error(error);
		throw error;
	}
};
@brettstack
Copy link
Collaborator

Hey, thanks for the report. I wonder if this is something with Typescript configuration? I can do simple:

import { createServer, proxy } from '@vendia/serverless-express';

console.log(createServer, proxy)

with my babel config and I get:

[Function: createServer] [Function: proxy]

The way the package is structured, it has an index.js at the top-level https://github.com/vendia/serverless-express/blob/master/index.js that simply re-exports the index.js in src/index.js which is where those functions are defined.

If you run ls node_modules/@vendia/serverless-express what do you get (is the index.js there)?

@brettstack
Copy link
Collaborator

I just tried with basic TypeScript by running:

npx tsc lambda.ts
node lambda.js

And I got the same [Function: createServer] [Function: proxy] output.

If you don't want to spend time figuring out what's going on (why the top-level index.js isn't exporting src/index.js) you can simply import like import { createServer, proxy } from '@vendia/serverless-express/src', however, this isn't guaranteed to continue to work forever (though it's unlikely we'll change/break it)

@smasilamani-cfins
Copy link
Author

Thank you for getting back on this quickly, here is my tsconfig.json and we do not use babel at all.

{
	"compilerOptions": {
		"module": "commonjs",
		"declaration": true,
		"removeComments": true,
		"emitDecoratorMetadata": true,
		"experimentalDecorators": true,
		"esModuleInterop": true,
		"target": "ES2017",
		"sourceMap": true,
		"outDir": "./dist",
		"baseUrl": ".",
		"incremental": true,
		"noUnusedLocals": true,
		"noUnusedParameters": true,
		"noImplicitReturns": true,
		"noImplicitThis": true,
		"lib": ["ES2019"],
		"skipLibCheck": true,
		"alwaysStrict": true,
		"forceConsistentCasingInFileNames": true,
		"isolatedModules": true,
		"moduleResolution": "node",
		"noFallthroughCasesInSwitch": true,
		"resolveJsonModule": true,
		"strict": false,
		"paths": {
			"@app/*": ["src/app/*"],
			"@clearance/*": ["src/clearance/*"],
			"@submission/*": ["src/submission/*"],
			"@shared/*": ["src/shared/*"],
			"@external_services/*": ["src/external_services/*"]
		}
	},
	"exclude": ["node_modules", ".serverless", ".webpack", "_warmup", ".vscode", "dist"]
}

ls command :

$ ls -ltr node_modules/@vendia/serverless-express
total 28
-rwxrwxrwx 1 root root  5161 Oct 26  1985 README.md    
-rwxrwxrwx 1 root root  3609 Oct 26  1985 package.json 
-rwxrwxrwx 1 root root    59 Oct 26  1985 middleware.js
-rwxrwxrwx 1 root root 11357 Oct 26  1985 LICENSE      
-rwxrwxrwx 1 root root    54 Oct 26  1985 index.js     
-rwxrwxrwx 1 root root  2508 Oct 26  1985 CHANGELOG.md 
drwxrwxrwx 1 root root  4096 Jan  4 17:59 src

Without running my copy command all I can see is undefined (last line in the output)
Code:

import { Handler } from 'aws-lambda';
import Express from 'express';
import { Server } from 'http';

import { INestApplication } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';
import { DSServerConstants } from '@shared/models/server.constants';
import { createServer, proxy } from '@vendia/serverless-express';

import { bootstrap } from './main';

console.log(createServer, proxy);

Output:

offline: Offline [http for lambda] listening on http://localhost:3002
offline: Function names exposed for local invocation by aws-sdk:
           * index: ds-iq-submission-service-local-index

   ┌─────────────────────────────────────────────────────────────────────────┐
   │                                                                         │
   │   ANY | http://localhost:3003/local                                     │
   │   POST | http://localhost:3003/2015-03-31/functions/index/invocations   │
   │   ANY | http://localhost:3003/local/{proxy*}                            │
   │   POST | http://localhost:3003/2015-03-31/functions/index/invocations   │
   │                                                                         │
   └─────────────────────────────────────────────────────────────────────────┘

Watchpack Error (initial scan): Error: EACCES: permission denied, lstat '/mnt/c/hiberfil.sys'
Watchpack Error (initial scan): Error: EACCES: permission denied, lstat '/mnt/c/pagefile.sys'
Watchpack Error (initial scan): Error: EACCES: permission denied, lstat '/mnt/c/swapfile.sys'
offline: [HTTP] server ready: http://localhost:3003 �
offline:
offline: Enter "rp" to replay the last request
asset src/index.js 22.9 MiB [emitted] (name: src/index) 1 related asset
cached modules 20 MiB [cached] 3590 modules
runtime modules 1.03 KiB 5 modules
./node_modules/agentkeepalive/index.js 169 bytes [code generated]
webpack compiled successfully in 3486 ms
Serverless: Watching for changes...
No issues found.

offline: ANY /local/api-json (λ: index)
undefined undefined

Since my copy command works fine, we should be good for now and when I get time, I can look into it in detail.

Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants