<commit_before>import PouchDB from 'pouchdb'
import pouchdbFind from 'pouchdb-find'
import { DOCTYPE_FILES } from './doctypes'

let pluginLoaded = false

/*
  For each doctype we have some parameters:
  cozy._offline[doctype] = {
    database: pouchdb database
    replication: the pouchdb replication
    replicationPromise: promise of replication
    interval: repeated replication interval
  }
*/

export function init (cozy, { options = {}, doctypes = [] }) {
  for (let doctype of doctypes) {
    createDatabase(cozy, doctype, options)
  }
}

// helper

function getInfo (cozy, doctype) {
  cozy._offline = cozy._offline || []
  cozy._offline[doctype] = cozy._offline[doctype] || {}
  return cozy._offline[doctype]
}

export function getDoctypes (cozy) {
  cozy._offline = cozy._offline || []
  return Object.keys(cozy._offline)
}

//
// DATABASE
//

export function hasDatabase (cozy, doctype) {
  return getDatabase(cozy, doctype) !== undefined
}

export function getDatabase (cozy, doctype) {
  return getInfo(cozy, doctype).database
}

export function setDatabase (cozy, doctype, database) {
  cozy._offline[doctype].database = database
  return getDatabase(cozy, doctype)
}

function errorDatabase (doctype) {
  return new Error(`You should add this doctype: ${doctype} to offline.`)
}

export function createDatabase (cozy, doctype, options = {}) {
  if (!pluginLoaded) {
    PouchDB.plugin(pouchdbFind)
    pluginLoaded = true
  }

  if (hasDatabase(cozy, doctype)) {
    return Promise.resolve(getDatabase(cozy, doctype))
  }

  setDatabase(cozy, doctype, new PouchDB(doctype, options))
  return createIndexes(cozy, doctype).then(() => getDatabase(cozy, doctype))
}

export function destroyDatabase (cozy, doctype) {
  if (!hasDatabase(cozy, doctype)) {
    return Promise.resolve(false)
  }

  return stopRepeatedReplication(cozy, doctype)
    .then(() => stopReplication(cozy, doctype))
    .then(() => getDatabase(cozy, doctype).destroy())
    .then(response => {
      setDatabase(cozy, doctype, undefined)
      return response
    })
}

export function destroyAllDatabase (cozy) {
  const doctypes = getDoctypes(cozy)
  const destroy = (doctype) => destroyDatabase(cozy, doctype)
  return Promise.all(doctypes.map(destroy))
}

function createIndexes (cozy, doctype) {
  if (doctype === DOCTYPE_FILES) {
    return getDatabase(cozy, doctype).createIndex({index: {fields: ['dir_id']}})
  }
  return Promise.resolve()
}

//
// REPLICATION
//

export function hasReplication (cozy, doctype) {
  return getReplication(cozy, doctype) !== undefined
}

function getReplication (cozy, doctype) {
  return getInfo(cozy, doctype).replication
}

function setReplication (cozy, doctype, replication) {
  cozy._offline[doctype].replication = replication
  return getReplication(cozy, doctype)
}

function getReplicationUrl (cozy, doctype) {
  return cozy.authorize()
    .then(credentials => {
      const basic = credentials.token.toBasicAuth()
      return (cozy._url + '/data/' + doctype).replace('//', `//${basic}`)
    })
}

function getReplicationPromise (cozy, doctype) {
  return getInfo(cozy, doctype).replicationPromise
}

function setReplicationPromise (cozy, doctype, promise) {
  cozy._offline[doctype].replicationPromise = promise
  return getReplicationPromise(cozy, doctype)
}

export function replicateFromCozy (cozy, doctype, options = {}) {
  return setReplicationPromise(cozy, doctype, new Promise((resolve, reject) => {
    if (!hasDatabase(cozy, doctype)) {
      return reject(errorDatabase(doctype))
    }
    if (options.live === true) {
      return reject(new Error('You can\'t use `live` option with Cozy couchdb.'))
    }

    getReplicationUrl(cozy, doctype)
      .then(url => setReplication(cozy, doctype,
        getDatabase(cozy, doctype).replicate.from(url, options).on('complete', (info) => {
          setReplication(cozy, doctype, undefined)
          resolve(info)
        }).on('error', (err) => {
          console.warn(`ReplicateFromCozy '${doctype}' Error:`)
          console.warn(err)
          setReplication(cozy, doctype, undefined)
          reject(err)
        })
      ))
  }))
}

export function stopReplication (cozy, doctype) {
  if (!getDatabase(cozy, doctype) || !hasReplication(cozy, doctype)) {
    return Promise.resolve()
  }

  return new Promise(resolve => {
    try {
      getReplicationPromise(cozy, doctype).then(() => {
        resolve()<commit_msg>handling custom code on replication complete or error<commit_after>import PouchDB from 'pouchdb'
import pouchdbFind from 'pouchdb-find'
import { DOCTYPE_FILES } from './doctypes'

let pluginLoaded = false

/*
  For each doctype we have some parameters:
  cozy._offline[doctype] = {
    database: pouchdb database
    replication: the pouchdb replication
    replicationPromise: promise of replication
    interval: repeated replication interval
  }
*/

export function init (cozy, { options = {}, doctypes = [] }) {
  for (let doctype of doctypes) {
    createDatabase(cozy, doctype, options)
  }
}

// helper

function getInfo (cozy, doctype) {
  cozy._offline = cozy._offline || []
  cozy._offline[doctype] = cozy._offline[doctype] || {}
  return cozy._offline[doctype]
}

export function getDoctypes (cozy) {
  cozy._offline = cozy._offline || []
  return Object.keys(cozy._offline)
}

//
// DATABASE
//

export function hasDatabase (cozy, doctype) {
  return getDatabase(cozy, doctype) !== undefined
}

export function getDatabase (cozy, doctype) {
  return getInfo(cozy, doctype).database
}

export function setDatabase (cozy, doctype, database) {
  cozy._offline[doctype].database = database
  return getDatabase(cozy, doctype)
}

function errorDatabase (doctype) {
  return new Error(`You should add this doctype: ${doctype} to offline.`)
}

export function createDatabase (cozy, doctype, options = {}) {
  if (!pluginLoaded) {
    PouchDB.plugin(pouchdbFind)
    pluginLoaded = true
  }

  if (hasDatabase(cozy, doctype)) {
    return Promise.resolve(getDatabase(cozy, doctype))
  }

  setDatabase(cozy, doctype, new PouchDB(doctype, options))
  return createIndexes(cozy, doctype).then(() => getDatabase(cozy, doctype))
}

export function destroyDatabase (cozy, doctype) {
  if (!hasDatabase(cozy, doctype)) {
    return Promise.resolve(false)
  }

  return stopRepeatedReplication(cozy, doctype)
    .then(() => stopReplication(cozy, doctype))
    .then(() => getDatabase(cozy, doctype).destroy())
    .then(response => {
      setDatabase(cozy, doctype, undefined)
      return response
    })
}

export function destroyAllDatabase (cozy) {
  const doctypes = getDoctypes(cozy)
  const destroy = (doctype) => destroyDatabase(cozy, doctype)
  return Promise.all(doctypes.map(destroy))
}

function createIndexes (cozy, doctype) {
  if (doctype === DOCTYPE_FILES) {
    return getDatabase(cozy, doctype).createIndex({index: {fields: ['dir_id']}})
  }
  return Promise.resolve()
}

//
// REPLICATION
//

export function hasReplication (cozy, doctype) {
  return getReplication(cozy, doctype) !== undefined
}

function getReplication (cozy, doctype) {
  return getInfo(cozy, doctype).replication
}

function setReplication (cozy, doctype, replication) {
  cozy._offline[doctype].replication = replication
  return getReplication(cozy, doctype)
}

function getReplicationUrl (cozy, doctype) {
  return cozy.authorize()
    .then(credentials => {
      const basic = credentials.token.toBasicAuth()
      return (cozy._url + '/data/' + doctype).replace('//', `//${basic}`)
    })
}

function getReplicationPromise (cozy, doctype) {
  return getInfo(cozy, doctype).replicationPromise
}

function setReplicationPromise (cozy, doctype, promise) {
  cozy._offline[doctype].replicationPromise = promise
  return getReplicationPromise(cozy, doctype)
}

export function replicateFromCozy (cozy, doctype, options = {}) {
  return setReplicationPromise(cozy, doctype, new Promise((resolve, reject) => {
    if (!hasDatabase(cozy, doctype)) {
      return reject(errorDatabase(doctype))
    }
    if (options.live === true) {
      return reject(new Error('You can\'t use `live` option with Cozy couchdb.'))
    }

    getReplicationUrl(cozy, doctype)
      .then(url => setReplication(cozy, doctype,
        getDatabase(cozy, doctype).replicate.from(url, options).on('complete', (info) => {
          options.onComplete && options.onComplete(info)
          setReplication(cozy, doctype, undefined)
          resolve(info)
        }).on('error', (err) => {
          options.onError && options.onError(err)
          console.warn(`ReplicateFromCozy '${doctype}' Error:`)
          console.warn(err)
          setReplication(cozy, doctype, undefined)
          reject(err)
        })
      ))
  }))
}

export function stopReplication (cozy, doctype) {
  if (!getDatabase(cozy, doctype) || !hasReplication(cozy, doctype)) {
    return Promise.resolve()
  }

  return new Promise(resolve => {
    try {
      getReplicationPromise(cozy, doctype).then(() => {
        resolve()
{'fraction_non_alphanumeric': 0.12860162420736457, 'fraction_numerical': 0.0, 'mean_word_length': 4.016741071428571, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 27, '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': '3046133', 'n_tokens_mistral': 3042, 'n_tokens_neox': 2869, 'n_words': 658}