Middy: validator: Module not found 'avj-keywords'

Created on 1 Sep 2020  路  15Comments  路  Source: middyjs/middy

When using serverless with serverless-bundle.

Warning

If you use serverless with serverless-bundle you will run into a build issue (Module not found 'ajv-keywords') with the default configuration. See #560 for details. You can use v1.2.0 or set ajvPlugins to {} to remove all plugins and work around this issue.

https://github.com/middyjs/middy/pull/552#issuecomment-684126761

bug

Most helpful comment

I maybe having the same issues as @ThomasKiec here.
Setup = monorepo, typescript, serverless.

When using validator version 1.4.0 with webpack 4 and serverless-webpack I was getting a whole bunch of WARNINGS, but it still bundled and worked.
An example warning:
WARNING in ../../node_modules/ajv-errors/README.md 1:0
Module parse failed: Unexpected character '#' (1:0)

Then I tried to upgrade from webpack 4 to webpack 5 and am now getting
ERROR in ../../node_modules/ajv-errors/LICENSE 1:4
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

But as it is an error it won't bundle.

I seem to have gotten around this for now with the following ignore loader regex, though it is hacky
{ test: /(?=(ajv-.*))((?=.*(\.(?!(js|json)\b).*))|(?=.*(LICENSE)))/, loader: 'ignore-loader' },

1 thing I did notice was that if you update following it works .. (well it did for me and makes no sense why)
const pckJson = require(../../ajv-${p}/package.json) pluginsInstances[p] = require(../../ajv-${p}/${pckJson.main})

to:

const pckJson = require(../../ajv-${p}/package.json); const mainFile =../../ajv-${p}/${pckJson.main}; pluginsInstances[p] = require(mainFile);

But I cannot change the node_module on my CI server.

Hopefully this will help someone else :)

All 15 comments

Having the same issue here. Webpack doesn't seem to get along well with dynamic require's.
Could this be fixed without putting the burden on users?

I'm open to solutions, however, it must be able to run in node v10.

v1.3.2 has the fix in it. cc @renanwilliam

Great, updated our project and everything back to work like a charm :)

@willfarrell I have the same issue but in my case this happens since the fixes in v1.3.2. Before v1.3.2 everything worked just fine

@ThomasKiec Can you describe your build process, using any extra serverless plugins that might touch the code?

In my current project I use serverless with the serverless-webpack plugin.

No problems here but I'm using ^1.4.0

I maybe having the same issues as @ThomasKiec here.
Setup = monorepo, typescript, serverless.

When using validator version 1.4.0 with webpack 4 and serverless-webpack I was getting a whole bunch of WARNINGS, but it still bundled and worked.
An example warning:
WARNING in ../../node_modules/ajv-errors/README.md 1:0
Module parse failed: Unexpected character '#' (1:0)

Then I tried to upgrade from webpack 4 to webpack 5 and am now getting
ERROR in ../../node_modules/ajv-errors/LICENSE 1:4
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

But as it is an error it won't bundle.

I seem to have gotten around this for now with the following ignore loader regex, though it is hacky
{ test: /(?=(ajv-.*))((?=.*(\.(?!(js|json)\b).*))|(?=.*(LICENSE)))/, loader: 'ignore-loader' },

1 thing I did notice was that if you update following it works .. (well it did for me and makes no sense why)
const pckJson = require(../../ajv-${p}/package.json) pluginsInstances[p] = require(../../ajv-${p}/${pckJson.main})

to:

const pckJson = require(../../ajv-${p}/package.json); const mainFile =../../ajv-${p}/${pckJson.main}; pluginsInstances[p] = require(mainFile);

But I cannot change the node_module on my CI server.

Hopefully this will help someone else :)

Same issue, ton of output with Module parse failed: Unexpected token

Same issue on our end

I maybe having the same issues as @ThomasKiec here.
Setup = monorepo, typescript, serverless.

When using validator version 1.4.0 with webpack 4 and serverless-webpack I was getting a whole bunch of WARNINGS, but it still bundled and worked.
An example warning:
WARNING in ../../node_modules/ajv-errors/README.md 1:0
Module parse failed: Unexpected character '#' (1:0)

Then I tried to upgrade from webpack 4 to webpack 5 and am now getting
ERROR in ../../node_modules/ajv-errors/LICENSE 1:4
Module parse failed: Unexpected token (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

But as it is an error it won't bundle.

I seem to have gotten around this for now with the following ignore loader regex, though it is hacky
{ test: /(?=(ajv-.*))((?=.*(\.(?!(js|json)\b).*))|(?=.*(LICENSE)))/, loader: 'ignore-loader' },

1 thing I did notice was that if you update following it works .. (well it did for me and makes no sense why)
const pckJson = require(../../ajv-${p}/package.json) pluginsInstances[p] = require(../../ajv-${p}/${pckJson.main})

to:

const pckJson = require(../../ajv-${p}/package.json); const mainFile =../../ajv-${p}/${pckJson.main}; pluginsInstances[p] = require(mainFile);

But I cannot change the node_module on my CI server.

Hopefully this will help someone else :)

Having this same issue

Going to re-open for now to ensure this is well tested in the next version. I may reach out for help testing.

Using the excellent patch-package, I was able to fix this issue using webpack's require.context API:

diff --git a/node_modules/@middy/validator/index.js b/node_modules/@middy/validator/index.js
index 36abf97..e001846 100644
--- a/node_modules/@middy/validator/index.js
+++ b/node_modules/@middy/validator/index.js
@@ -138,7 +138,9 @@ function getPlugins (p) {
   try {
     /* Fixes #560: Webpack needs explicit paths for dynamic imports */
     const pckJson = require(`../../ajv-${p}/package.json`)
-    pluginsInstances[p] = require(`../../ajv-${p}/${pckJson.main}`)
+    const mainFile = `./ajv-${p}/${pckJson.main}`
+    const pluginRequire = require.context('../../', true, /ajv-\w+\/.+\.js$/)
+    pluginsInstances[p] = pluginRequire(mainFile)
   } catch (e) {
     console.error(`Error getting plugins ${e.message}`)
   }

After setting up patch-package in your project, you'll need to replicate the above changes in node_modules/@middy/validator/index.js and run npx patch-package @middy/validator to fix your copy of @middy/validator.

If, like me, you don't want ajv-i18n included in your Lambda bundle, you can update node_modules/@middy/validator/index.js with a negative lookahead in the regular expression:

diff --git a/node_modules/@middy/validator/index.js b/node_modules/@middy/validator/index.js
index 36abf97..ab19f06 100644
--- a/node_modules/@middy/validator/index.js
+++ b/node_modules/@middy/validator/index.js
@@ -138,7 +138,9 @@ function getPlugins (p) {
   try {
     /* Fixes #560: Webpack needs explicit paths for dynamic imports */
     const pckJson = require(`../../ajv-${p}/package.json`)
-    pluginsInstances[p] = require(`../../ajv-${p}/${pckJson.main}`)
+    const mainFile = `./ajv-${p}/${pckJson.main}`
+    const pluginRequire = require.context('../../', true, /ajv-(?!i18n)\w+\/.+\.js$/)
+    pluginsInstances[p] = pluginRequire(mainFile)
   } catch (e) {
     console.error(`Error getting plugins ${e.message}`)
   }

If you'd like to exclude other Ajv plugins, update the regular expression accordingly:

diff --git a/node_modules/@middy/validator/index.js b/node_modules/@middy/validator/index.js
index 36abf97..647d5a6 100644
--- a/node_modules/@middy/validator/index.js
+++ b/node_modules/@middy/validator/index.js
@@ -138,7 +138,9 @@ function getPlugins (p) {
   try {
     /* Fixes #560: Webpack needs explicit paths for dynamic imports */
     const pckJson = require(`../../ajv-${p}/package.json`)
-    pluginsInstances[p] = require(`../../ajv-${p}/${pckJson.main}`)
+    const mainFile = `./ajv-${p}/${pckJson.main}`
+    const pluginRequire = require.context('../../', true, /ajv-(?!i18n|keywords)\w+\/.+\.js$/)
+    pluginsInstances[p] = pluginRequire(mainFile)
   } catch (e) {
     console.error(`Error getting plugins ${e.message}`)
   }

Confirmed, this is a non-issue in v2

Was this page helpful?
0 / 5 - 0 ratings

Related issues

erikhagreis picture erikhagreis  路  4Comments

acdoussan picture acdoussan  路  3Comments

vladgolubev picture vladgolubev  路  4Comments

lmammino picture lmammino  路  3Comments

willfarrell picture willfarrell  路  3Comments