Commercetools Category Exporter error: CategoryExporter is not a constructor

57 Views Asked by At

I am trying to initialise the commercetools category importer as per the JS example at the bottom of: https://commercetools.github.io/nodejs/cli/category-exporter.html (and also linked from https://docs.commercetools.com/import-export/overview)

My JS looks like this (almost identical to the example)

import CategoryExporter from '@commercetools/category-exporter'
import fs from 'fs'
import { options } from '../config/options.js';

const optionsImporter = {
  apiConfig: {
    apiUrl: options.apiURL,
    host: options.authURL,
    project_key: options.projectKey,
    credentials: {
      clientId: options.clientID,
      clientSecret: options.clientSecret
    }
  },
  accessToken: '123456xxxx0987654321',
  predicate: 'key="my-desired-key"'
};

const logger = {
  error: console.error,
  warn: console.warn,
  info: console.log,
  debug: console.debug,
};

const categoryExporter = new CategoryExporter(optionsImporter, logger);

// Register error listener
outputStream.on('error', errorHandler);

outputStream.on('finish', () => console.log('done with export'));

categoryExporter.run(outputStream);

Im my package.json I have added a command to run this from an npm shortcut.

"importer:test": "node ./src/import/categoryImporter.js",

When I run this I get the following error:

const categoryExporter = new CategoryExporter(optionsImporter, logger);
                         ^
TypeError: CategoryExporter is not a constructor

I have tried to rummage into the commerce-tools library, but it looks like it is exporting a class from the main.js

export default class CategoryExporter {

The library is here: https://github.com/commercetools/nodejs/blob/master/packages/category-exporter/src/main.js

And in my package.json I am using:

"@commercetools/category-exporter": "^4.0.0",

I did think I could try and downgrade the category-exporter version.

Another thing that crossed my mind it seems that commercetools uses a mixture of js and ts, and is using ts in a js file. But I assume that is separate to my bug.

I realise this is a lot of info and I don't really want to tweak a node_module, but if anyone has any experience with this would like to hear from you.

1

There are 1 best solutions below

0
lharby On

I ended up solving this through trial and error. But there are several omissions in the CommerceTools documentation linked to here (from the question) https://commercetools.github.io/nodejs/cli/category-exporter.html

Here is the final code:

import fs from 'fs';
import path from 'path';
import CategoryExporter from '@commercetools/category-exporter';
import { options } from '../config/options.js';

const url = `${options.authURL}/oauth/token?grant_type=client_credentials`;
const fileFinish = path.join(process.cwd(), 'src', 'import', 'logs', 'log.json');
let token;

const authHeader = new Headers();
authHeader.append("Authorization", "Basic " + btoa(options.clientID + ":" + options.secret));
const raw = "";

const requestOptions = {
  method: 'POST',
  headers: authHeader,
  body: raw,
  redirect: 'follow'
};

fetch(url, requestOptions)
  .then(response => response.text())
  .then(result => {
    const data = JSON.parse(result);
    token = data.access_token;
    retriveCategoryExporter();
  })
  .catch(error => console.log('error', error));

const logger = {
  error: console.error,
  warn: console.warn,
  info: console.log,
  debug: console.debug,
};

const outputStream = fs.createWriteStream(fileFinish);

const errorHandler = (error) => console.log('error', error);

// Register error listener
const retriveCategoryExporter = () => {
  const optionsImporter = {
    apiConfig: {
      apiUrl: options.apiURL,
      host: options.authURL,
      projectKey: options.projectKey,
      credentials: {
        clientId: options.clientID,
        clientSecret: options.secret
      }
    },
    accessToken: token,
    predicate: 'key=""'
  };
  const categoryExporter = new CategoryExporter.default(optionsImporter, logger);
  outputStream.on('error', errorHandler);
  outputStream.on('finish', () => console.log('done with export'));
  categoryExporter.run(outputStream);
}

Main things to note.

const categoryExporter = new CategoryExporter(optionsImporter, logger);

Is now

const categoryExporter = new CategoryExporter.default(optionsImporter, logger);

The original code uses an errorHandler function as a callback, but no such handler exists in the documentation example. So I wrote my own.

const errorHandler = (error) => console.log('error', error);

This of course merely logs stuff to the console but I also thought it would be useful to pipe any errors to a file. So I used the path module and added this

const fileFinish = path.join(process.cwd(), 'src', 'import', 'logs', 'log.json');

const outputStream = fs.createWriteStream(fileFinish);

And then all of the config as well as the error handling gets wrapped inside the retriveCategoryExporter function, which is called after a successful fetch promise is returned.

So

const retriveCategoryExporter = () => {
  const optionsImporter = {
    apiConfig: {
    // blah blah config   
   };
  const categoryExporter = new CategoryExporter.default(optionsImporter, logger);
  outputStream.on('error', errorHandler);
  outputStream.on('finish', () => console.log('done with export'));
  categoryExporter.run(outputStream);
}

This is all now working, and I believe an improvement on the documentation.