Highly confusing express.Router() issue - express

I have a large application build with NestJS that I deploy using the serverless framework. I have been doing this for some time and everything has been great. A couple of days ago I had to update to Nestjs 7 and I have been experiencing a lot of issues bootstrapping my application when it is deployed to aws. After going through countless frustrating attempts to resolve the issue it appears it's actually nothing to do with the Nestjs/serverless bootstrapping process at all and apollo-server-express was unable to access the express router - failing with the error:
express_1.default.Router is not a function
Finally I realised that when I import express directly and try and access express.Router() I have the same issue. So I made a very simple test:
lambda.ts:
import { Context, Handler } from "aws-lambda";
import express from "express";
export const handler: Handler = async (event: any, context: Context) => {
console.log("Import express:", express);
console.log("Test express app: ", express());
console.log("Test router:", express.Router());
/* express.Router() ->
ERROR TypeError: express_1.default.Router is not a function at
/var/task/dist/lambda.js:19:51 at Generator.next (<anonymous>) at
/var/task/dist/lambda.js:8:71 at new Promise (<anonymous>) at
__awaiter (/var/task/dist/lambda.js:4:12) at exports.handler (/var/task/dist/lambda.js:16:39) at
Runtime.handler (/var/task/serverless_sdk/index.js:9:131872) at
Runtime.handleOnce (/var/runtime/Runtime.js:66:25)
*/
};
This fails with the error in the comment as previously stated. Here are the other files:
serverless.yml:
service: xxxxx
app: xxxx
tenant: xxxxx
plugins:
- serverless-pseudo-parameters
- serverless-prune-plugin
- serverless-deployment-bucket
provider:
name: aws
runtime: nodejs12.x
region: eu-west-1
stage: dev
timeout: 29
memorySize: 3008
deploymentBucket:
name: ${self:service}-${self:custom.currentStage}-deployment-bucket
serverSideEncryption: AES256
custom: ${file(./serverless-common.yml):custom}
package:
include:
- ./dist/**
exclude:
- node_modules/aws-sdk/**
functions:
index:
handler: ./dist/lambda.handler
name: bm-${self:custom.currentStage}-express-test
events:
- http:
path: "/{proxy+}"
method: POST
package.json:
{
"name": "#xxx/XXXXXX",
"version": "0.1.13",
"dependencies": {
"express": "4.17.1"
},
"devDependencies": {
"serverless-deployment-bucket": "1.1.1",
"serverless-prune-plugin": "1.4.2",
"serverless-pseudo-parameters": "2.5.0",
"ts-node": "^8.7.0",
"tsconfig-paths": "^3.7.0",
"tslint": "5.12.1",
"tslint-config-prettier": "^1.18.0",
"typescript": "^3.8.3"
}
}
tsconfig.json:
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"#root/*": ["src/*"]
},
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"outDir": "dist",
"esModuleInterop": true
},
"include": ["*"],
"exclude": ["**/node_modules/**/*", "dist"]
}
I would like to highlight that this code only fails once deployed to lambda. It runs fine locally which would make indicate that perhaps something was up with the packaging process but the zip file contains the correct code and dependencies.
I have been working on this problem for ages before narrowing it down to this. If anybody is able to shed any light on the above that would be greatly appreciated as it's obviously blocking me.
Many thanks
UPDATE:
OK it appears that if I:
import Router from 'express/lib/router'
then I get a router instance. This is the same instance the express index should export.
So I am close but this feels wrong, I haven't changed anything, I feel like I have some kind of incorrect module configuration or something.
So why can't I do express.Router(). Any ideas would be greatly appreciated.
UPDATE:
In the end I patched apollo-server-express so that it gets the router instance from lib/router and then everything works as expected.
I obviously do not want to do this so I really need to work out what's causing this.
Patched ApolloServer.js: https://gist.github.com/TreeMan360/8dc8373ffebe2b24ff51df42090fcb52
UPDATE:
Another related issue has developed in that the headers are returned as part of the response body e.g:
HTTP/1.1200OKX-Powered-By: ExpressAccess-Control-Allow-Origin: *Content-Type: application/json;charset=utf-8Content-Length: 155ETag: W/"9b-mbrRmusN4ADjvBFA5aFJNLyRMHs"Date: Sat,
04Apr202014: 35: 09GMTConnection: keep-alive{
"data": {
"memberLoginHook": {
"id": "1bb4ca87-d9f6-4ccb-a2a4-0249b19699b3",
"occupation": "C3PO",
"positions": [
{
"id": "f4deaf82-ad87-472b-82ab-c78d08138526"
}
]
}
}
}
It is also worth noting I have found someone else who has the same issue:
https://forum.serverless.com/t/highly-confusing-express-router-issue/10987/8

i’m aware what trigger the issue, very strange bug has very strange solution.
Try lo disable Serverless Framework Enterprise (if it’s enabled), you can just comment the tenant and app rows into your serverless.yml file, and deploy the app again.
I think that there’s a bug in the last version of the serverless-sdk.

Related

How can I prevent flaky tests when Cypress testing elements with "v-b-toggle" in a Bitbucket pipeline?

We have a Vue2-based frontend application which uses v-b-toggle to expand/collapse elements on when clicked. When running Cypress tests (either component or e2e tests) locally (CLI and UI), we have not seen the elements fail to expand or collapse. However when running on our Bitbucket pipelines, they will occasionally fail. Has anybody had this issue, and come across a solution?
We can't reproduce this locally, and it only happens intermittently in our pipeline. We've resorted to skipping most of these tests.
I believe this Github issue shows the same behaviour: https://github.com/cypress-io/cypress/issues/7810
More details:
Versions in package.json
"bootstrap-vue": "^2.21.2"
"cypress": "^10.4.0",
"vue": "^2.6.12",
Scripts used for UI and CLI (pipeline) testing:
"test:e2e:ui": "TZ=Etc/UTC cypress open --e2e --browser=electron",
"test:e2e": "TZ=Etc/UTC cypress run --e2e --browser=electron",
"test:component:ui": "TZ=Etc/UTC cypress open --component --browser=electron",
"test:component": "TZ=Etc/UTC cypress run --component --browser=electron"
cypress.config.js:
const { defineConfig } = require("cypress");
module.exports = defineConfig({
env: {
local_url: "http://localhost:8080/",
},
video: false,
screenshotOnRunFailure: true,
defaultCommandTimeout: 8000,
chromeWebSecurity: false, // Disabled to prevent errors with iframes. Would need to reenable if checking for CORS errors in the future.
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
return require("./cypress/plugins/index.js")(on, config);
},
experimentalSessionAndOrigin: true,
baseUrl: "http://localhost:8080",
},
component: {
setupNodeEvents(on, config) {},
specPattern: "src/**/*spec.{js,jsx,ts,tsx}",
devServer: {
framework: "vue-cli",
bundler: "webpack",
},
},
});
Happy to provide more information if required.

How to get mdx file support (linting) in VS Code?

I have a vue.js project with the storybook addon. I am trying to write a story using the Docs addon which allows you to write stories in .mdx, I am having trouble getting linting to work in vs code.
Thanks in advance and any help would be much appreciated!
I am using this sample project found here https://github.com/vueschool/storybook-fundamentals/tree/master.
The sample project has "eslint": "^6.7.2" installed.
I have installed "eslint-plugin-mdx": "^1.8.2"
I have the following extensions installed
My ES lint config looks like this, as suggested by https://github.com/mdx-js/eslint-mdx
{
"extends": ["plugin:mdx/recommended"]
}
It seems like vs code is picking up the mdx file but no linting seems to be happening, I'm I doing something wrong?
Also I have added the following to VS Code settings but it does not seem to be doing much
If this helps anyone. there is a dependency on eslint-plugin-react for eslint-mdx to work.
check https://github.com/mdx-js/eslint-mdx/issues/229
my eslint config looks like this for reference.
"root": true,
"env": {
"node": true
},
"extends": [
"eslint:recommended", "plugin:mdx/recommended", "plugin:react/recommended"
],
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"settings": {
"react": {
"version": "detect"
}
}

Cannot find module '#/assets/<file-name-here>.svg'. #vue/cli Version: 4.2.3 and 4.3.1

General jist:
import Image from '#/assets/default-profile-picture.svg'
//ERROR: Cannot find module '#/assets/default-profile-picture.svg'.Vetur(2307)
I have spent the better part of today trying to find a solution to this. I know there are a lot of other posts like this one, but they are all outdated (all over a year old).
I've just generated a clean Vue CLI app, and still have the same issue.
I'm using Vue CLI Version 4.2.3, and just attempted using Vue CLI Version 4.3.1, but ran into the same issue.
I have checked that the file is in assets.
I have checked that the filename is spelled correctly.
I have a feeling this is a webpack issue, as require() would not work when called using typescript.
I have tried creating vue.config.js and manually setting the path for assets.
Project setup configuration:
Features: Babel, TS, Router, ESLint
not class-style syntax
Babel used alongside Typescript
No history mode for router
eslint with error prevention only
Lint on save
Configs placed in package.json.
Error in Component.vue
<script lang="ts">
import Vue from 'vue'
/* Cannot find module '#/assets/default-profile-picture.svg'.Vetur(2307) */
import Image from '#/assets/default-profile-picture.svg'
export default Vue.extend({
components: {
},
props: [
'employeeImage',
'employeeName',
'employeeAge',
'employeeSalary'
],
data () {
return {
marked: false,
result: [],
name: this.employeeName,
age: this.employeeAge,
salary: this.employeeSalary
}
},
computed: {
compClasses: function () {
return {
marked: this.marked
}
},
imageDefault: function () {
if (this.employeeImage === '') {
console.log('employee image empty: ' + this.employeeImage)
return '#/assets/default-profile-picture.svg'
} else {
console.log('employee image set: ' + this.employeeImage)
return this.employeeImage
}
}
}
})
</script>
Typescript Config
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"#/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"/src/**/*.*",
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
What am I doing wrong?
Thanks in advance!
Please keep this in mind, that this answer is not a solution but more like a work-around for this issue by the time this question has been asked/answered for vue-svg-loader(#vue/cli Version: 4.2.3 and 4.3.1).
You can use absolute path instead of using # to reference the file when you want to import .vue components. Here is an example:
Instead of this:
Read more about this issue and any possible solutions on official repository for this issue on GitHub:
Typescript Cannot find module '#/assets/svg/register.svg?inline' #92
Typescript does not support svg files.
Create a svg.d.ts file in your project source folder with the following content:
declare module '*.svg';
and restart your editor

How to workaround the "Unexpected Token Operator (>)" error when packaging a React app?

I am having some problems building the distributable package for a React app.
I'm trying to execute the following sentence:
rimraf dist && env-cmd .env cross-env NODE_ENV=production webpack -p --config ./config/webpack/prod.js
And receiving this error:
ERROR in a86e50ffd4893c44fdfd.app.js from UglifyJs Unexpected token:
operator (>) [a86e50ffd4893c44fdfd.app.js:10679,43]
The line indicated in that trace corresponds to one of the libraries being loaded as dependencies, and not to the actual code of my app. This is the line itself (line 10679 corresponds to the declaration of the const method with the arrow function):
const DEFAULT_DISPLAY_LABEL_FOR_NULL_VALUES = '';
/* unused harmony export DEFAULT_DISPLAY_LABEL_FOR_NULL_VALUES */
const getAllColumnLabels = (columnLabels) => {
const columnNames = [];
columnLabels.forEach((value) => {
columnNames.push(value.label);
});
return columnNames;
};
At first I thought it could be related to Babel config, but it is identical to another project which is building correctly. The content of my .babelrc file is shown below, loaded using babel-preset-env:
{
"presets": [
[
"env", {
"modules": false,
"targets": {
"browsers": [
"Chrome >= 52",
"FireFox >= 44",
"Safari >= 7",
"Explorer 11",
"last 4 Edge versions"
]
},
"useBuiltIns": true
}
]
]
}
An additional test to rule out some possibilities has been done using the default presets for Babel, though no success was achieved with this test.
{
"presets": [
[
"env",
{
"modules": false
}
]
]
}
The settings in tsconfig.json could also be of interest, so i'm showing them here even though they also are identical to the ones in this another project mentioned above, which builds correctly:
{
"compilerOptions": {
"target": "es6",
"module": "es6",
"lib": ["dom", "es2017"],
"moduleResolution": "node",
"declaration": false,
"noImplicitAny": false,
"sourceMap": true,
"jsx": "react",
"noLib": false,
"allowJs": true,
"suppressImplicitAnyIndexErrors": true,
"skipLibCheck": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
},
"compileOnSave": true,
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
I've tried to delete node_modules and re-install the dependencies, also played setting uglify to false in the env for Babelrc, but surprisingly (at least, to me!) it didnt help.
There is a thread in the webpack-contrib Github site which is marked as closed but I didnt find anything that helped me.
Any ideas? I have some experience with npm but this issue certainly is blocking me.
Thanks!
Updating webpack to version 4 (currently 4.17) solved the problem. A few other dependencies needed to be updated to work properly with webpack 4, most importantly the Extract Text Webpack Plugin hasn't at this moment a stable release that works with webpack4, but the 4.0.0-beta works around the issue and may be used until a better replacement is found.

Karma, Browserify on React is failing on LESS

I'm learning how to use React, and in turn use Karma as the test runner. I'm running Karma with browserify / reactify (mocha+kai). Whenever I run npm test, I get the following error:
ERROR [framework.browserify]: bundle error
ERROR [framework.browserify]:
/Users/user/Projects/example-d3-react/src/d3Chart.less:1
.d3 {
^
ParseError: Unexpected token
ERROR [karma]: [TypeError: Not a string or buffer]
This happens on all LESS files in the project. I have tried adding a LESS preprocessor to the karma.conf like so:
preprocessors: {
'src/*.less': ['less'],
'tests/**/*.js': ['browserify']
},
browserify: {
debug: true,
transform: [ 'reactify' ]
},
lessPreprocessor: {
options: {
paths: ['src'],
save: true,
rootpath: './'
},
additionalData: {
modifyVars: {
'bodyColor': 'grey',
'secondBoxColor': 'blue'
},
globalVars: {
'globalBoxColor': 'red'
}
},
transformPath: function(path) {
console.log("transforming");
return path.replace(/\.less$/, '.compiled.css');
}
},
Add the preprocessor explicitly to the config: plugins: ['karma-less-preprocessor']
None of the suggested answers helped me, but in case anyone is experiencing this problem, the solution that worked for me is just adding the project-specific less transform to the package.json file. E.g:
{
...
"browserify": {
"exclude": "*.spec.js",
"transform": [
"node-lessify",
"browserify-ng-html2js"
]
},
...
}
Build broke when doing this, since I was using the cmd line transform when building application through NPM. Removed the cmd line transform part since the package.json transform will apply the transform programmatically, and now it works again.