少年は困っていた。
node-fetch がfetchできない。
ReferenceError: fetch is not defined
at Client.request (/var/task/node_modules/amazon-cognito-identity-js/lib/Client.js:55:3)
at /var/task/node_modules/amazon-cognito-identity-js/lib/CognitoUser.js:333:18
at AuthenticationHelper.getLargeAValue (/var/task/node_modules/amazon-cognito-identity-js/lib/AuthenticationHelper.js:96:4)
at CognitoUser.authenticateUserDefaultAuth (/var/task/node_modules/amazon-cognito-identity-js/lib/CognitoUser.js:309:24)
at CognitoUser.authenticateUser (/var/task/node_modules/amazon-cognito-identity-js/lib/CognitoUser.js:270:16)
at /var/task/dist/index.js:69:21
at new Promise (<anonymous>)
at fetchCredentials (/var/task/dist/index.js:68:12)
at cognitoProvider (/var/task/dist/index.js:65:18)
at async Runtime.exports.handler (/var/task/dist/index.js:34:31)
環境
- TypeScript 3.7
- Node.js 12.13.1
- AWS Lambda
やろうとしていたこと
エンドユーザーがHTTP通信を介してLambdaに認証情報を送り、それをバックエンドAPIで独自認証し、CognitoIdPoolから得たCredentials情報を返すLambdaを作成していた。
初期構築時も同じ問題に詰まったが、Module内に書き込むことでなんとか問題を解決することが出来た。
しかし、 node-fetchは2度刺す。
二度 刺すっ・・・・・!
Lambdaのリポジトリをcodepipelineを用いたCI/CD環境へと移行する際に再度問題が発生。
再度同じエラーが発生するようになった。
しかしリポジトリにnode_modulesをプッシュしている人はいるのだろうか、いやいない。私もプッシュをしていないその一人だった。
あれ、これどうやって実行するんだ……?
あらゆる記事を探しまくった結果解決を得ることが出来たのでここに記しておきたい。
結局公式に丁寧に書いてくれてたんだけどね。
npmのReadmeによると
This library uses the Fetch API. For older browsers or in Node.js, you may need to include a polyfill. For example.
このライブラリではfetchAPIを利用するため、古いブラウザやNode.jsでは以下のようにpolyfillを行う必要があります。
※polyfill = 隙間家具のイメージ。APIを利用するために準備が必要ですよということ。
global.fetch = require('node-fetch');
var AmazonCognitoIdentity = require('amazon-cognito-identity-js');
やってることはnode-fetchをグローバルオブジェクトとして読み込み、呼び出した場所で扱えるようにしてるってわけですね。
なるほど。
まぁJavascriptだったんで、Typescriptとして動くように書き換えます。
import Global = NodeJS.Global;
export interface GlobalWithCognitoFix extends Global {
fetch: any
}
declare const global: GlobalWithCognitoFix;
global.fetch = require('node-fetch').default;
こんな感じでfetchAPIを使用するコードでimportしてやるとfetchAPIが機能するようになります。
ここで注意して欲しいのが、fetchAPIを含むライブラリよりも先にimportが必要なので、脳死でコードの先頭に置いておくと良いと思います。