Node.js
Passport
loopback

loopback-passportを使う時に「The model type must be a constructor」が出た話

More than 3 years have passed since last update.

Node.js loopback-passport (loopback-component-passport) を使おうとして、下記のようなエラーがでた。

assert.js:93
  throw new assert.AssertionError({
        ^
AssertionError: The model type must be a constructor
    at Function.registry.getModelByType (***/node_modules/loopback/lib/registry.js:286:3)
    at PassportConfigurator.setupModels (***/node_modules/loopback-component-passport/lib/passport-configurator.js:32:50)
    at Object.<anonymous> (***/server/server.js:26:22)   
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:929:3

そもそも、loopback-passportにはloopback-example-passportとして使用例が用意されていて、当然試しました。
上記のエラーは改めて自分で作ってみようとした時に起きたエラーです。

Node.jsのことを十分に理解していない状態で触っているので、これがのせいじゃないのという気もしていますが。。。

エラーメッセージでググると、loopback-example-passportのissuesで下記のようなのも引っかかります。
Node.jsのお作法を知っていれば、sourcesに設定するものが足りないというパターンが多いのではないでしょうか。。
https://github.com/strongloop/loopback-example-passport/issues/25

自分の場合はこのパターンではなく、Node.jsのお作法の問題でした。
結論からいうと、下記を欠いていただけ。

server.js
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();

// Passport configurator                                                                              
var loopbackPassport = require('loopback-component-passport');
var PassportConfigurator = loopbackPassport.PassportConfigurator;
var passportConfigurator = new PassportConfigurator(app);

...

//忘れてたのはこれ↓
boot(app, __dirname);

...

//Initialize passport                                                                                 
passportConfigurator.init();

//エラーが出てるのはここ↓
passportConfigurator.setupModels({
    userModel: app.models.user,
    userIdentityModel: app.models.userIdentity,
    userCredentialModel: app.models.userCredential
});

Node.js 1.x系では、app.boot(__dirname)としていた部分。
2.x系からはプロジェクト別れたようです。
Loopbackの初期化(initialize/bootstrap)をする仕事をしてくれています。

ちなみに、__dirname は、nodeを起動する時のcurrentを指しているところを取得します。(docはこちら)

source設定を有効にするにも、これが必要だった、ということでしょうか。

ちなみに、Third-party loginの説明として、ここには1.x系の説明で書いてあります。
サンプルを2.x系で実行すると、こんな形でエラー出ました。
(まんま、メッセージに書いてある。親切ですねー。)

***/node_modules/loopback/lib/application.js:360
  throw new Error(
        ^
Error: `app.boot` was removed, use the new module loopback-boot instead
    at EventEmitter.app.boot (***/node_modules/loopback/lib/application.js:360:9)
    at Object.<anonymous> (***/server/server.js:22:5)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:929:3