function generateFunctionsFiles ({ suffix, factories, entryFolder }) {
  const braceOpen = '{' // a hack to be able to create a single brace open character in handlebars

  const sortedFactories = sortFactories(Object.values(factories))

  // sort the factories, and split them in three groups:
  // - transform: the transform functions
  // - impure: the functions that depend on `math` or `mathWithTransform` (directly or indirectly),
  // - pure: the rest
  const pureFactories = []
  const impureFactories = []
  const transformFactories = []
  sortedFactories
    .filter(factory => !DEPRECATED_FACTORIES[factory.fn])
    .forEach(factory => {
      if (isTransform(factory)) {
        transformFactories.push(factory)
      } else if (
        factory.dependencies.includes('math') ||
        factory.dependencies.includes( 'mathWithTransform') ||
        factory.dependencies.includes( 'classes') ||
        isTransform(factory) ||
        factory.dependencies.some(dependency => {
          return impureFactories.find(f => f.fn === stripOptionalNotation(dependency))
        })
      ) {
        impureFactories.push(factory)
      } else {
        pureFactories.push(factory)
      }
    })

  // a map containing:
  // {
  //   'sqrt': true,
  //   'subset': true,
  //   ...
  // }
  const pureExists = {
    config: true
  }
  pureFactories.forEach(factory => {
    pureExists[factory.fn] = true
  })

  const impureExists = {
    ...pureExists
  }
  impureFactories.forEach(factory => {
    impureExists[factory.fn] = true
  })

  const math = sortedFactories
    .filter(factory => !isClass(factory))
    .filter(factory => !isTransform(factory))
    .map(factory => {
      return {
        name: factory.fn,
        renamed: DEPRECATED_FACTORIES[factory.fn],
        mappedName: FACTORY_NAMES_ES6_MAPPING[factory.fn]
      }
    })

  const classes = sortedFactories
    .filter(factory => isClass(factory))
    .map(factory => ({ name: factory.fn }))

  const data = {
    suffix,
    pureFactories: pureFactories.map(factory => {
      const name = FACTORY_NAMES_ES6_MAPPING[factory.fn] || factory.fn

      return {
        braceOpen,
        factoryName: findKey(factories, factory), // TODO: find a better way to match the factory names
        eslintComment: name === 'SQRT1_2'
          ? ' // eslint-disable-line camelcase'
          : undefined,
        name,
        dependencies: factory.dependencies
          .map(stripOptionalNotation)
          .filter(dependency => !IGNORED_DEPENDENCIES_ES6[dependency])
          .filter(dependency => {
            // TODO: this code is duplicated. extract it in a separate function
            if (!pureExists[dependency]) {
              if (factory.dependencies.includes(dependency)) {
                throw new Error(`Required dependency "${dependency}" missing for factory "${factory.fn}" (suffix: ${suffix})`)
              }

              return false
            }

            return true
          })
          .map(dependency => ({ name: dependency })),
        formerly: factory.meta?.formerly
      }
    }),

    impureFactories: impureFactories.map(factory => {
      const name = FACTORY_NAMES_ES6_MAPPING[factory.fn] || factory.fn

      return {
        braceOpen,
        factoryName: findKey(factories, factory), // TODO: find a better way to match the factory names
        eslintComment: name === 'SQRT1_2'
          ? ' // eslint-disable-line camelcase'
          : undefined,
        name,
        dependencies: factory.dependencies
          .map(stripOptionalNotation)
          .filter(dependency => !IGNORED_DEPENDENCIES_ES6[dependency])
          .filter(dependency => {
            if (dependency === 'math' || dependency === 'mathWithTransform' || dependency === 'classes') {
              return true
            }

            // TODO: this code is duplicated. extract it in a separate function
            if (!impureExists[dependency]) {
              // if (factory.dependencies.includes(dependency)) {
              //   throw new Error(`Required dependency "${dependency}" missing for factory "${factory.fn}"`)
              // }

              return false
            }

            return true
          })
          .map(dependency => ({ name: dependency }))
      }
    }),

    transformFactories: transformFactories.map(factory => {
      const name = FACTORY_NAMES_ES6_MAPPING[factory.fn] || factory.fn

      return {
        braceOpen,
        factoryName: findKey(factories, factory), // TODO: find a better way to match the factory names
        eslintComment: name === 'SQRT1_2'
          ? ' // eslint-disable-line camelcase'
          : undefined,
        name,
        dependencies: factory.dependencies
          .map(stripOptionalNotation)
          .filter(dependency => !IGNORED_DEPENDENCIES_ES6[dependency])
          .filter(dependency => {
            if (dependency === 'math' || dependency === 'mathWithTransform' || dependency === 'classes') {
              return true
            }

            // TODO: this code is duplicated. extract it in a separate function
            if (!impureExists[dependency]) {
              // if (factory.dependencies.includes(dependency)) {
              //   throw new Error(`Required dependency "${dependency}" missing for factory "${factory.fn}"`)
              // }

              return false
            }

            return true
          })
          .map(dependency => ({ name: dependency }))
      }
    }),

    math,
    classes
  }

  // create file with all functions: functionsAny.generated.js, functionsNumber.generated.js
  fs.writeFileSync(path.join(entryFolder, 'pureFunctions' + suffix + '.generated.js'), pureFunctionsTemplate(data))

  // create file with all functions: impureFunctions.generated.js, impureFunctions.generated.js
  fs.writeFileSync(path.join(entryFolder, 'impureFunctions' + suffix + '.generated.js'), impureFunctionsTemplate(data))
}
Generate index files like
  pureFunctionsAny.generated.js
  impureFunctionsAny.generated.js