thgh / vercel-sapper

Vercel builder for Sapper with SSR enabled
MIT License
191 stars 25 forks source link

Getting 'Did you write `module.exports = app`? error' #52

Closed armincerf closed 4 years ago

armincerf commented 4 years ago

Cannot reproduce outside of vercel by running in dev or production mode, started from the standard sapper template and everything worked fine until I added an auth flow using express-passport.

If I remove the passport code it all works fine, but I have no visibility into what is going wrong at all here. No logs in vercel and no error other than the 'module.exports' one.

This is my server.js with some of the session code taken out, but it is still giving the error when I try and load any page.

import sirv from 'sirv'
import express from 'express'
import compression from 'compression'
import * as sapper from '@sapper/server'
import {
    config
} from 'dotenv'
import Auth0Strategy from 'passport-auth0'
import passport from 'passport'
import session from 'express-session';
import bodyParser from 'body-parser';
import util from 'util';
import url from 'url';
import querystring from 'querystring';

config();

const {
    PORT,
    NODE_ENV
} = process.env
const dev = NODE_ENV === 'development'

// Configure Passport to use Auth0
var strategy = new Auth0Strategy({
        domain: process.env.AUTH0_DOMAIN,
        clientID: process.env.AUTH0_CLIENT_ID,
        clientSecret: process.env.AUTH0_CLIENT_SECRET,
        callbackURL: process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/callback'
    },
    function (accessToken, refreshToken, extraParams, profile, done) {
        // accessToken is the token to call Auth0 API (not needed in the most cases)
        // extraParams.id_token has the JSON Web Token
        // profile has all the information from the user
        return done(null, profile);
    }
);

// You can use this section to keep a smaller payload
passport.serializeUser(function (user, done) {
    done(null, user);
});

passport.deserializeUser(function (user, done) {
    done(null, user);
});

const sessionConfig = {
    name: "session.sid",
    secret: "foo",
    resave: false,
    saveUninitialized: true,
    cookie: {
        httpOnly: true,
        maxAge: 31536000,
    } 
};

const app = express()
    .use(bodyParser.json())

    .get(
        '/login',
        passport.authenticate('auth0', {
            scope: 'openid email profile'
        }),
        (req, res) => {
            res.redirect('/');
        }
    )
    .get('/callback', (req, res, next) => {
        passport.authenticate('auth0', (err, user, info) => {
            if (err) {
                return next(err);
            }
            if (!user) {
                return res.redirect('/login');
            }
            req.logIn(user, (err) => {
                if (err) {
                    return next(err);
                }
                const returnTo = req.session.returnTo;
                delete req.session.returnTo;
                res.redirect(returnTo || '/');
            });
        })(req, res, next);
    })
    .get('/logout', (req, res) => {
        req.logout();

        var returnTo = req.protocol + '://' + req.hostname;
        var port = req.connection.localPort;
        if (port !== undefined && port !== 80 && port !== 443) {
            returnTo += ':' + port;
        }

        var logoutURL = new url.URL(
            util.format('https://%s/v2/logout', process.env.AUTH0_DOMAIN)
        );
        var searchString = querystring.stringify({
            client_id: process.env.AUTH0_CLIENT_ID,
            returnTo: returnTo
        });
        logoutURL.search = searchString;
        req.session.destroy(function (err) {
            if (err) {
                console.error(err);
            } else {
                res.clearCookie(sessionConfig.name)
                res.redirect(logoutURL);
            }
        });
    })
    .use(
        compression({
            threshold: 0
        }),
        sirv("static", {
            dev
        }),
        sapper.middleware({
            session: (req) => {
                const user = req.session.passport ? req.session.passport.user : null;
                return {
                    user
                };
            },
        })
    )
    .listen(PORT, (err) => {
        if (err) console.log("error", err);
    });

    module.exports = app;
thgh commented 4 years ago

express().listen() returns void, so you want:

const app = express()
  .use()
  .use()....
app.listen() // separate line
export default app

or

const app = (module.exports = express())
  .use()
  .use()
  .listen()
jonadeline commented 3 years ago

Hi @thgh Just ran a deployment and getting the error : https://web-ahgqiryew.vercel.app/ I didnt do any changes on my vercel conf files or my server.js since the previous deployment so Im not sure what's happening there. Here is my server.js file :

import http from "http";
import sirv from "sirv";
import polka from "polka";
import { createProxyMiddleware } from "http-proxy-middleware";
import compression from "compression";
import * as sapper from "@sapper/server";
import { i18nMiddleware } from "./i18n.js";
const { json } = require("body-parser");
require("dotenv").config();

const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === "development";
const prod = NODE_ENV === "production";

let apiTarget = "http://localhost:5001/my-app/us-central1/";
if (prod) apiTarget = "https://us-central1-myapp-next.cloudfunctions.net/";

const app = polka()
  .use(
    "/api",
    createProxyMiddleware({
      target: apiTarget,
      changeOrigin: true,
      logLevel: "debug",
      pathRewrite: {
        "^/api": "",
      },
    })
  )
  .use(json())
  .use(
    compression({ threshold: 0 }),
    sirv("static", { dev }),
    i18nMiddleware(),
    sapper.middleware()
  )
  .listen(PORT, (err) => {
    if (err) console.log("error", err);
  });

module.exports = app;
thgh commented 3 years ago
-  .listen(PORT, (err) => {
+app.listen(PORT, (err) => {