<commit_before>#     NoFlo - Flow-Based Programming for JavaScript
#     (c) 2013-2016 TheGrid (Rituwall Inc.)
#     (c) 2013 <NAME>, Nemein
#     NoFlo may be freely distributed under the MIT license
#
# This is the Node.js version of the ComponentLoader.

{_} = require 'underscore'
path = require 'path'
fs = require 'fs'
loader = require '../ComponentLoader'
internalSocket = require '../InternalSocket'
utils = require '../Utils'
nofloGraph = require '../Graph'
manifest = require 'fbp-manifest'

# We allow components to be un-compiled CoffeeScript
CoffeeScript = require 'coffee-script'
if typeof CoffeeScript.register != 'undefined'
  CoffeeScript.register()
babel = require 'babel-core'

class ComponentLoader extends loader.ComponentLoader
  writeCache: (options, modules, callback) ->
    filePath = path.resolve @baseDir, options.manifest
    fs.writeFile filePath, JSON.stringify(modules, null, 2),
      encoding: 'utf-8'
    , callback

  readCache: (options, callback) ->
    options.discover = false
    manifest.load.load @baseDir, options, callback

  prepareManifestOptions: ->
    options = {}
    options.runtimes = @options.runtimes or []
    options.runtimes.push 'noflo' if options.runtimes.indexOf('noflo') is -1
    options.recursive = if typeof @options.recursive is 'undefined' then true else @options.recursive
    options.manifest = 'fbp.json' unless options.manifest
    options

  readModules: (modules, callback) ->
    compatible = modules.filter (m) -> m.runtime in ['noflo', 'noflo-nodejs']
    for m in compatible
      @libraryIcons[m.name] = m.icon if m.icon

      if m.noflo?.loader
        loaderPath = path.resolve @baseDir, m.base, m.noflo.loader
        @componentLoaders.push loaderPath

      for c in m.components
        @components["#{m.name}/#{c.name}"] = path.resolve @baseDir, c.path

    # Inject subgraph component
    if path.extname(__filename) is '.js'
      @components.Graph = path.resolve __dirname, '../../components/Graph.js'
    else
      @components.Graph = path.resolve __dirname, '../../components/Graph.coffee'

    return callback null unless @componentLoaders.length
    done = _.after @componentLoaders.length, callback
    @componentLoaders.forEach (loaderPath) =>
      loader = require loaderPath
      @registerLoader loader, (err) ->
        return callback err if err
        done null

  listComponents: (callback) ->
    if @processing
      @once 'ready', =>
        callback @components
      return
    return callback @components if @components

    @ready = false
    @processing = true

    manifestOptions = @prepareManifestOptions()
    @components = {}

    if @options.cache and not @failedCache
      @readCache manifestOptions, (err, modules) =>
        if err
          @failedCache = true
          @processing = false
          @listComponents callback
          return
        @readModules modules, (err) =>
          @ready = true
          @processing = false
          @emit 'ready', true
          callback @components if callback
      return

    manifest.list.list @baseDir, manifestOptions, (err, modules) =><commit_msg>Set @components only after successful read<commit_after>#     NoFlo - Flow-Based Programming for JavaScript
#     (c) 2013-2016 TheGrid (Rituwall Inc.)
#     (c) 2013 <NAME>, Nemein
#     NoFlo may be freely distributed under the MIT license
#
# This is the Node.js version of the ComponentLoader.

{_} = require 'underscore'
path = require 'path'
fs = require 'fs'
loader = require '../ComponentLoader'
internalSocket = require '../InternalSocket'
utils = require '../Utils'
nofloGraph = require '../Graph'
manifest = require 'fbp-manifest'

# We allow components to be un-compiled CoffeeScript
CoffeeScript = require 'coffee-script'
if typeof CoffeeScript.register != 'undefined'
  CoffeeScript.register()
babel = require 'babel-core'

class ComponentLoader extends loader.ComponentLoader
  writeCache: (options, modules, callback) ->
    filePath = path.resolve @baseDir, options.manifest
    fs.writeFile filePath, JSON.stringify(modules, null, 2),
      encoding: 'utf-8'
    , callback

  readCache: (options, callback) ->
    options.discover = false
    manifest.load.load @baseDir, options, callback

  prepareManifestOptions: ->
    options = {}
    options.runtimes = @options.runtimes or []
    options.runtimes.push 'noflo' if options.runtimes.indexOf('noflo') is -1
    options.recursive = if typeof @options.recursive is 'undefined' then true else @options.recursive
    options.manifest = 'fbp.json' unless options.manifest
    options

  readModules: (modules, callback) ->
    compatible = modules.filter (m) -> m.runtime in ['noflo', 'noflo-nodejs']
    for m in compatible
      @libraryIcons[m.name] = m.icon if m.icon

      if m.noflo?.loader
        loaderPath = path.resolve @baseDir, m.base, m.noflo.loader
        @componentLoaders.push loaderPath

      for c in m.components
        @components["#{m.name}/#{c.name}"] = path.resolve @baseDir, c.path

    # Inject subgraph component
    if path.extname(__filename) is '.js'
      @components.Graph = path.resolve __dirname, '../../components/Graph.js'
    else
      @components.Graph = path.resolve __dirname, '../../components/Graph.coffee'

    return callback null unless @componentLoaders.length
    done = _.after @componentLoaders.length, callback
    @componentLoaders.forEach (loaderPath) =>
      loader = require loaderPath
      @registerLoader loader, (err) ->
        return callback err if err
        done null

  listComponents: (callback) ->
    if @processing
      @once 'ready', =>
        callback @components
      return
    return callback @components if @components

    @ready = false
    @processing = true

    manifestOptions = @prepareManifestOptions()

    if @options.cache and not @failedCache
      @readCache manifestOptions, (err, modules) =>
        if err
          @failedCache = true
          @processing = false
          @listComponents callback
          return
        @components = {}
        @readModules modules, (err) =>
          @ready = true
          @processing = false
          @emit 'ready', true
          callback @components if callback
      return

    @components = {}
    manifest.list.list @baseDir, manifestOptions, (err, modules) =>
{'fraction_non_alphanumeric': 0.10929568527918782, 'fraction_numerical': 0.004758883248730965, 'mean_word_length': 2.9629164047768697, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6630623', 'n_tokens_mistral': 1819, 'n_tokens_neox': 1758, 'n_words': 530}