When changing the app descriptor for my ACE app, it throws TypeError: self.register is not a function

Hi all, pretty new to connect app development and node+react in general.

I have a connect app which is just Atlassian connect express plus react, using Typescript for the react parts. Running the app is fine and I can install it in my instance.
However, if I make changes to the app descriptor (atlassian-connect.json) while the server is running , it crashes out with the following error:

Re-registering due to atlassian-connect.json change
C:\Users\dominic.cousins\GitHub\cloud-command-centre\node_modules\atlassian-connect-express\lib\index.js:66
                        self.register(true);
                             ^

TypeError: self.register is not a function
    at FSWatcher.<anonymous> (C:\Users\dominic.cousins\GitHub\cloud-command-centre\node_modules\atlassian-connect-express\lib\index.js:66:30)
    at FSWatcher.emit (events.js:223:5)
    at FSEvent.FSWatcher._handle.onchange (internal/fs/watchers.js:131:12)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

The error seems to be occurring in the js provided by atlassian-connect-express but I can’t believe that is actually the problem. Any help is appreciated and I will provide anything I can as it’s requested. Such files can be found below.

Cheers, Dominic

My package.json:

{
    "name": "starter-app",
    "version": "1.0.0",
    "private": true,
    "license": "UNLICENSED",
    "scripts": {
        "start": "node app.js",
        "build": "tsc",
        "restart": "yarn build && yarn start"
    },
    "engines": {
        "node": "^12"
    },
    "dependencies": {
        "@types/node": "^12.12.20",
        "atlassian-connect-express": "^4.0.1",
        "body-parser": "^1.19.0",
        "compression": "^1.7.4",
        "cookie-parser": "^1.4.4",
        "dotenv": "^8.2.0",
        "errorhandler": "^1.5.1",
        "express": "^4.17.1",
        "express-hbs": "*",
        "morgan": "^1.9.1",
        "pg": "^7.15.0",
        "sequelize": "^4.42.0",
        "static-expiry": "^0.0.11",
        "typescript": "^3.7.3"
    }
}

My app.js (which is very similar to the default ACE file):

// Import Environmental Variables
require('dotenv').config();

// Startup Text
const os = require('os');
console.log("________________________________________________________");
console.log("|                                                                                   |");
console.log("|                     Starter App                                            |");
console.log("|                                                                                   |");
if(process.env.NODE_ENV === "production") {
console.log("|         !         PRODUCTION  MODE         !                   |");
} else {
console.log("|                   DEVELOPMENT MODE                           |");
}
console.log("|                                                                                  |");
console.log("|______________________________________________________|");
console.log("");

// Initialize database connection
const Sequelize = require('sequelize');
const sequelize = new Sequelize(process.env.POSTGRES_DB_DATABASE, process.env.POSTGRES_DB_USERNAME, process.env.POSTGRES_DB_PASSWORD, {
    host: process.env.POSTGRES_DB_HOST,
    dialect: 'postgres',
});

// Requirements
const express = require('express');
const bodyParser = require('body-parser');
const compression = require('compression');
const cookieParser = require('cookie-parser');
const errorHandler = require('errorhandler');
const morgan = require('morgan');
const ac = require('atlassian-connect-express');
process.env.PWD = process.env.PWD || process.cwd();
const expiry = require('static-expiry');
const hbs = require('express-hbs');
const http = require('http');
const path = require('path');
const staticDir = path.join(__dirname, 'public');
const viewsDir = __dirname + '/views';
const routes = require('./dist');
const app = express();
const addon = ac(app);
const port = addon.config.port();
const devEnv = app.get('env') === 'development';

// Setup
app.set('port', port);
app.engine('hbs', hbs.express3({partialsDir: viewsDir}));
app.set('view engine', 'hbs');
app.set('views', viewsDir);

function skipLog(req, res) {
    return !!req.url.includes("db-check");
}

// Middleware - Logs
app.use(morgan(devEnv ? 'dev' : 'combined', {skip: skipLog}));
// Middleware - Request Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
// Middleware - GZip
app.use(compression());
// Middleware - General
app.use(addon.middleware());
// Middleware - Static Resource Caching
app.use(expiry(app, {dir: staticDir, debug: devEnv}));
// HBS Helper
hbs.registerHelper('furl', function(url){ return app.locals.furl(url); });

// Static Resources
app.use(express.static(staticDir));

// Show Errors if in Dev Mode
if (devEnv) app.use(errorHandler());

// Routes - this are the main TypeScript files which
routes(app, addon, sequelize);

addon.on('host_settings_saved', function (clientKey, data) {
    console.log(`Starter App Installed for ${clientKey} with data`, data);
});

// Catch Exceptions
process.on('unhandledRejection', (reason, p) => {
    console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});

// Boot
http.createServer(app).listen(port, function(){
    console.log(" - Local URL:      http://" + os.hostname() + ":" + port);
    console.log(" - Base URL:       " + process.env.BASE_URL);
});

Hey,

I remember having a similar problem. I can’t fully remember what the problem was, but by inspecting the ACE code (in node_modules) you can see the line that’s causing the error. It’s used (AFAIK) for registering the addon on your instance in case something changes in the app descriptor (atlassian-connect.json). The way to reregister is by adding credentials.json in your project root, so the first thing I’d do is check if you have it and if the credentials inside are correct.

The next thing I’d do is check the validity of atlassian-connect (try Connect Validator).

Hope this’ll be of some use. Cheers

Hi,

Thanks for your response and suggestions. My credentials.json file was missing. I have created one and pointed it at my dev instance but the app still throws the same error when I change the app descriptor. I have also checked my app descriptor using the validator and it has returned OK.

I did notice the error is in the ACE code but I can’t work out how this would happen. I’m also pretty sure it’s code for automatic registration. Perhaps it’s missing a dependency? Though yarn should handle and warn me about that.

The error still exists so if you do remember how you fixed, do tell. For now it doesn’t seem too important - it’s mostly an annoyance that I have to re-install my app when I change the descriptor

From browsing the atlassian-connect-express code in node-modules it looks like it requires ngrok for auto registration which I don’t use. From the code, however, it should return an error message mentioning ngrok. So it looks like I can’t have auto registration without ngrok which I can’t use (long story).

I think something else is going on though, as it’s throwing a weird error instead of printing a message - maybe the value of ‘this’ is populated unexpectedly so when it goes self.register(true) the type of self doesn’t have register?

If I’m correct about ngrok being required for auto-registration then this problem won’t affect me. I’ll still try to fix the error if anyone has suggestions