cloudant / nodejs-cloudant

Cloudant Node.js client library
Apache License 2.0
255 stars 90 forks source link

Error with latest version 4.2.0 #389

Closed huineng closed 5 years ago

huineng commented 5 years ago

Please read these guidelines before opening an issue.

Bug Description

1. Steps to reproduce and the simplest code sample possible to demonstrate the issue

Installing the latest version published a few hours ago i have now an error

  throw new Error(`Failed to load plugin - ${e.message}`);
            ^

Error: Failed to load plugin - Cannot find module '../plugins/cookieauth'

2. What you expected to happen

webpack compilation completes. Or maybe some instructions with breaking changes

thanks

3. What actually happened

a message about a missing plugin

Environment details

full stack

            throw new Error(`Failed to load plugin - ${e.message}`);
            ^

Error: Failed to load plugin - Cannot find module '../plugins/cookieauth'
    at /Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:1047:19
    at Array.forEach (<anonymous>)
    at CloudantClient._addPlugins (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:1007:13)
    at new CloudantClient (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:997:10)
    at Cloudant (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:298:24)
    at new cloudant_CloudantLib (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:2606:43)
    at Module.fc4506377efd97041428 (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:2616:27)
    at __webpack_require__ (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:20:30)
    at /Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:84:18
    at Object.<anonymous> (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:87:10)
    at Module._compile (internal/modules/cjs/loader.js:868:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:879:10)
    at Module.load (internal/modules/cjs/loader.js:731:32)
    at Function.Module._load (internal/modules/cjs/loader.js:644:12)
    at Function.Module.runMain (internal/modules/cjs/loader.js:931:10)
    at internal/main/run_main_module.js:17:11
emlaver commented 5 years ago

Hi @huineng, please share the code that initializes the Cloudant client and where the error occurs in your workspace.

huineng commented 5 years ago

this is how i initialise cloudant , it always worked until the latest version

import Cloudant from '@cloudant/cloudant';
import { Credentials } from './cfenv';
import { utils } from './utils';
class CloudantLib {
    constructor() {
        const cfg = Credentials('cloudant');
        this.cloudant = Cloudant({ url: cfg.url });
        this.cloudant.ping()
            .then((b) => {
            utils.logInfo('$cloudant (constructor): Initialisation done', JSON.stringify(b));
        })
            .catch((err) => {
            utils.logError('$cloudant (constructor): Initialisation failed', err);
        });
    }
}
export const cloudant = new CloudantLib().cloudant;

i also have a typescript error now

WARNING in ./node_modules/@cloudant/cloudant/lib/client.js 105:21-63
Critical dependency: the request of a dependency is an expression
    at CommonJsRequireContextDependency.getWarnings (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/webpack/lib/dependencies/ContextDependency.js:40:18)
    at Compilation.reportDependencyErrorsAndWarnings (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/webpack/lib/Compilation.js:1416:24)
    at /Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/webpack/lib/Compilation.js:1221:10
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:20:1)
    at AsyncSeriesHook.lazyCompileHook (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/tapable/lib/Hook.js:154:20)
    at Compilation.finish (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/webpack/lib/Compilation.js:1216:28)
    at /Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/webpack/lib/Compiler.js:662:17
    at eval (eval at create (/Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
    at /Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/webpack/lib/Compilation.js:1148:12
    at /Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/node_modules/webpack/lib/Compilation.js:1060:9
    at processTicksAndRejections (internal/process/task_queues.js:75:11)
 @ ./node_modules/@cloudant/cloudant/cloudant.js
 @ ./node_modules/@sets/leap-common/lib/common/cloudant.js

ps this is the complete class as compiled by webpack (error is on line 74

webvpack.txt

emlaver commented 5 years ago

Is the file you attached the server.js from your stacktrace?

Error: Failed to load plugin - Cannot find module '../plugins/cookieauth'
    at /Users/guyhuinen/Documents/workspace/leap/leap/applications/expo/server/server.js:1047:19`

I'm not familiar with webpack. Can you share all your dependencies from package.json?

huineng commented 5 years ago

as you might now webpack like bable is a bundler so it will compile all js into one file

The problem is that your latest code is now doing dynamic requires, so webpack at time of bundling doesn't know what is being required (the variables only comes later and won't find the dynamic part anymore like './plugins/cookieauth'

I'm now stuck with this as there's no solution on my side

I've tested some possible solutions and one is to require upfront the plugins

const plugs = {
  cookieauth: require('../plugins/cookieauth')
}

and then to use it

case 'string':
          if (plugin === 'base' || plugin === 'default' || plugin === 'promises') {
            return; // noop
          }

          try {
            Plugin = plugs[plugin];
          } catch (e) {
            throw new Error(`Failed to load plugin - ${e.message}`);
          }

          cfg = {};
          break;

in this way the plugins are not dynamically required

I think longer run it's bette to avoid dynamic requires unless you move to import statements

let me know

smithsz commented 5 years ago

Hi @huineng, The Critical dependency: the request of a dependency is an expression warning is unavoidable I think. We can list the built-in plugins (see #390) so at least they'd get bundled correctly. Let me know what you think. Sam

smithsz commented 5 years ago

I've published a SNAPSHOT build for the PR mentioned above. Can you please confirm if this resolves the problem? Thanks.

@cloudant/cloudant@4.2.1-SNAPSHOT.2

huineng commented 5 years ago

well perfect , that works !

now, maybe just a favor , but users will still see the typescript warning (not error) for this require method

WARNING in ./node_modules/@cloudant/cloudant/lib/client.js 105:21-63
Critical dependency: the request of a dependency is an expression
    at CommonJsRequireContextDependency.getWarnings

There's an easy fix for this by just using a literal like

from

return require(this._buildPluginPath(pluginName));

to

return require(`${this._buildPluginPath(pluginName)}`);

that avoids a lot of linting , CI/CI warnings

this would be appreciated

smithsz commented 5 years ago

Thanks again for raise this issue @huineng.

The fix is now in the latest release - @cloudant/cloudant@4.2.1.

huineng commented 5 years ago

Perfect !!