// ets_tracing: off
import "../../../Operator";
import * as Cause from "../../../Cause";
import * as AR from "../../../Collections/Immutable/Array";
import * as A from "../../../Collections/Immutable/Chunk";
import * as Tp from "../../../Collections/Immutable/Tuple";
import * as T from "../../../Effect";
import { sequential } from "../../../Effect";
import * as E from "../../../Either";
import * as Ex from "../../../Exit";
import * as F from "../../../Fiber";
import { pipe } from "../../../Function";
import * as H from "../../../Hub";
import * as M from "../../../Managed";
import * as RM from "../../../Managed/ReleaseMap";
import * as O from "../../../Option";
import * as PR from "../../../Promise";
import * as Q from "../../../Queue";
import * as Ref from "../../../Ref";
import { ChannelExecutor, ChannelStateDoneTypeId, ChannelStateEffectTypeId, ChannelStateEmitTypeId } from "./_internal/executor";
import * as MH from "./_internal/mergeHelpers";
import * as P from "./_internal/primitives";
import { makeSingleProducerAsyncInput } from "./_internal/producer";
import * as C from "./core";
/**
 * Returns a new channel that is the same as this one, except the terminal value of the channel
 * is the specified constant value.
 *
 * This method produces the same result as mapping this channel to the specified constant value.
 */

export function as_(self, z2) {
  return map_(self, _ => z2);
}
/**
 * Returns a new channel that is the same as this one, except the terminal value of the channel
 * is the specified constant value.
 *
 * This method produces the same result as mapping this channel to the specified constant value.
 *
 * @ets_data_first as_
 */

export function as(z2) {
  return self => as_(self, z2);
}
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 */

export function catchAll_(self, f) {
  return catchAllCause_(self, cause => E.fold_(Cause.failureOrCause(cause), l => f(l), r => C.failCause(r)));
}
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 *
 * @ets_data_first catchAll_
 */

export function catchAll(f) {
  return self => catchAll_(self, f);
}
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 */

export function catchAllCause_(self, f) {
  return new P.Fold(self, new P.ContinuationK(_ => C.end(_), f));
}
/**
 * Returns a new channel that is the same as this one, except if this channel errors for any
 * typed error, then the returned channel will switch over to using the fallback channel returned
 * by the specified error handler.
 *
 * @ets_data_first catchAllCause_
 */

export function catchAllCause(f) {
  return self => catchAllCause_(self, f);
}
/**
 * Returns a new channel, which is the same as this one, except its outputs are filtered and
 * transformed by the specified partial function.
 */

export function collect_(self, f) {
  const collector = C.readWith(o => O.fold_(f(o), () => collector, out2 => zipRight_(C.write(out2), collector)), e => C.fail(e), z => C.end(z));
  return C.pipeTo_(self, collector);
}
/**
 * Returns a new channel, which is the same as this one, except its outputs are filtered and
 * transformed by the specified partial function.
 *
 * @ets_data_first collect_
 */

export function collect(f) {
  return self => collect_(self, f);
}
/**
 * Returns a new channel, which is the concatenation of all the channels that are written out by
 * this channel. This method may only be called on channels that output other channels.
 */

export function concatOut(self) {
  return concatAll(mapOut_(self, out => out));
}

function contramapReader(f) {
  return C.readWith(_in => zipRight_(C.write(_in), contramapReader(f)), err => C.fail(err), done => C.end(f(done)));
}

export function contramap_(self, f) {
  return C.pipeTo_(contramapReader(f), self);
}
/**
 * @ets_data_first contramap_
 */

export function contramap(f) {
  return self => contramap_(self, f);
}

function contramapInReader(f) {
  return C.readWith(_in => zipRight_(C.write(f(_in)), contramapInReader(f)), err => C.fail(err), done => C.end(done));
}

export function contramapIn_(self, f) {
  return C.pipeTo_(contramapInReader(f), self);
}
/**
 * @ets_data_first contramapIn_
 */

export function contramapIn(f) {
  return self => contramapIn_(self, f);
}

function contramapMReader(f) {
  return C.readWith(_in => zipRight_(C.write(_in), contramapMReader(f)), err => C.fail(err), done0 => C.fromEffect(f(done0)));
}

export function contramapEffect_(self, f) {
  return C.pipeTo_(contramapMReader(f), self);
}
/**
 * @ets_data_first contramapEffect_
 */

export function contramapEffect(f) {
  return self => contramapEffect_(self, f);
}

function contramapInMReader(f) {
  return C.readWith(_in => zipRight_(C.chain_(C.fromEffect(f(_in)), _ => C.write(_)), contramapInMReader(f)), err => C.fail(err), done => C.end(done));
}

export function contramapInEffect_(self, f) {
  return C.pipeTo_(contramapInMReader(f), self);
}
/**
 * @ets_data_first contramapInEffect_
 */

export function contramapInEffect(f) {
  return self => contramapInEffect_(self, f);
}

function doneCollectReader(builder) {
  return C.readWith(out => zipRight_(C.succeedWith(() => {
    builder.append(out);
  }), doneCollectReader(builder)), err => C.fail(err), done => C.end(done));
}
/**
 * Returns a new channel, which is the same as this one, except that all the outputs are
 * collected and bundled into a tuple together with the terminal value of this channel.
 *
 * As the channel returned from this channel collect's all of this channel's output into an in-
 * memory chunk, it is not safe to call this method on channels that output a large or unbounded
 * number of values.
 */


export function doneCollect(self) {
  return C.suspend(() => {
    const builder = A.builder();
    return C.chain_(C.pipeTo_(self, doneCollectReader(builder)), z => C.succeedWith(() => Tp.tuple(builder.build(), z)));
  });
}
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified effect completes. If the effect completes successfully before the underlying channel
 * is done, then the returned channel will yield the success value of the effect as its terminal
 * value. On the other hand, if the underlying channel finishes first, then the returned channel
 * will yield the success value of the underlying channel as its terminal value.
 */

export function interruptWhen_(self, io) {
  return mergeWith_(self, C.fromEffect(io), selfDone => MH.done(T.done(selfDone)), ioDone => MH.done(T.done(ioDone)));
}
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified effect completes. If the effect completes successfully before the underlying channel
 * is done, then the returned channel will yield the success value of the effect as its terminal
 * value. On the other hand, if the underlying channel finishes first, then the returned channel
 * will yield the success value of the underlying channel as its terminal value.
 *
 * @ets_data_first interruptWhen_
 */

export function interruptWhen(io) {
  return self => interruptWhen_(self, io);
}
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified promise is completed. If the promise is completed before the underlying channel is
 * done, then the returned channel will yield the value of the promise. Otherwise, if the
 * underlying channel finishes first, then the returned channel will yield the value of the
 * underlying channel.
 */

export function interruptWhenP_(self, promise) {
  return interruptWhen_(self, PR.await(promise));
}
/**
 * Returns a new channel, which is the same as this one, except it will be interrupted when the
 * specified promise is completed. If the promise is completed before the underlying channel is
 * done, then the returned channel will yield the value of the promise. Otherwise, if the
 * underlying channel finishes first, then the returned channel will yield the value of the
 * underlying channel.
 *
 * @ets_data_first interruptWhenP_
 */

export function interruptWhenP(promise) {
  return self => interruptWhenP_(self, promise);
}
/**
 * Returns a new channel that collects the output and terminal value of this channel, which it
 * then writes as output of the returned channel.
 */

export function emitCollect(self) {
  return C.chain_(doneCollect(self), t => C.write(t));
}
export function ensuring_(self, finalizer) {
  return C.ensuringWith_(self, _ => finalizer);
}
/**
 * @ets_data_first ensuring_
 */

export function ensuring(finalizer) {
  return self => ensuring_(self, finalizer);
}
export function foldChannel_(self, onErr, onSucc) {
  return C.foldCauseChannel_(self, _ => {
    return E.fold_(Cause.failureOrCause(_), err => onErr(err), cause => C.failCause(cause));
  }, onSucc);
}
/**
 * @ets_data_first foldChannel_
 */

export function foldChannel(onErr, onSucc) {
  return self => foldChannel_(self, onErr, onSucc);
}
/**
 * Returns a new channel that will perform the operations of this one, until failure, and then
 * it will switch over to the operations of the specified fallback channel.
 */

export function orElse_(self, that) {
  return catchAll_(self, _ => that);
}
/**
 * Returns a new channel that will perform the operations of this one, until failure, and then
 * it will switch over to the operations of the specified fallback channel.
 *
 * @ets_data_first orElse_
 */

export function orElse(that) {
  return self => orElse_(self, that);
}
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified function to the terminal value of this
 * channel.
 */

export function map_(self, f) {
  return C.chain_(self, z => succeed(f(z)));
}
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified function to the terminal value of this
 * channel.
 *
 * @ets_data_first map_
 */

export function map(f) {
  return self => map_(self, f);
}
/**
 * Returns a new channel, which is the same as this one, except the failure value of the returned
 * channel is created by applying the specified function to the failure value of this channel.
 */

export function mapError_(self, f) {
  return mapErrorCause_(self, cause => Cause.map_(cause, f));
}
/**
 * Returns a new channel, which is the same as this one, except the failure value of the returned
 * channel is created by applying the specified function to the failure value of this channel.
 *
 * @ets_data_first mapError_
 */

export function mapError(f) {
  return self => mapError_(self, f);
}
/**
 * A more powerful version of `mapError` which also surfaces the `Cause` of the channel failure
 */

export function mapErrorCause_(self, f) {
  return catchAllCause_(self, cause => C.failCause(f(cause)));
}
/**
 * A more powerful version of `mapError` which also surfaces the `Cause` of the channel failure
 *
 * @ets_data_first mapErrorCause_
 */

export function mapErrorCause(f) {
  return self => mapErrorCause_(self, f);
}

function runManagedInterpret(channelState, exec) {
  // eslint-disable-next-line no-constant-condition
  while (1) {
    switch (channelState._typeId) {
      case ChannelStateEffectTypeId:
        {
          return T.chain_(channelState.effect, () => runManagedInterpret(exec.run(), exec));
        }

      case ChannelStateEmitTypeId:
        {
          channelState = exec.run();
          break;
        }

      case ChannelStateDoneTypeId:
        {
          return T.done(exec.getDone());
        }
    }
  }

  throw new Error("Bug");
}

function toPullInterpret(channelState, exec) {
  switch (channelState._typeId) {
    case ChannelStateEffectTypeId:
      {
        return T.chain_(T.mapError_(channelState.effect, E.left), () => toPullInterpret(exec.run(), exec));
      }

    case ChannelStateEmitTypeId:
      {
        return T.succeed(exec.getEmit());
      }

    case ChannelStateDoneTypeId:
      {
        const done = exec.getDone();

        if (done._tag === "Success") {
          return T.fail(E.right(done.value));
        } else {
          return T.halt(Cause.map_(done.cause, E.left));
        }
      }
  }
}
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified effectful function to the terminal value
 * of this channel.
 */


export function mapEffect_(self, f) {
  return C.chain_(self, z => C.fromEffect(f(z)));
}
/**
 * Returns a new channel, which is the same as this one, except the terminal value of the
 * returned channel is created by applying the specified effectful function to the terminal value
 * of this channel.
 *
 * @ets_data_first mapEffect_
 */

export function mapEffect(f) {
  return self => mapEffect_(self, f);
}
/**
 * Returns a new channel, which is the merge of this channel and the specified channel, where
 * the behavior of the returned channel on left or right early termination is decided by the
 * specified `leftDone` and `rightDone` merge decisions.
 */

export function mergeWith_(self, that, leftDone, rightDone) {
  const m = M.map_(M.bind_(M.bind_(M.let_(M.bind_(M.do, "input", () => T.toManaged(makeSingleProducerAsyncInput())), "queueReader", ({
    input
  }) => fromInput(input)), "pullL", ({
    queueReader
  }) => toPull(queueReader[">>>"](self))), "pullR", ({
    queueReader
  }) => toPull(queueReader[">>>"](that))), ({
    input,
    pullL,
    pullR
  }) => {
    const handleSide = (exit, fiber, pull) => (done, both, single) => Ex.fold_(exit, cause => {
      const result = done(E.fold_(Cause.flipCauseEither(cause), _ => Ex.halt(_), _ => Ex.succeed(_)));
      MH.concrete(result);

      if (result._typeId === MH.DoneTypeId) {
        return T.succeed(C.fromEffect(T.zipRight_(F.interrupt(fiber), result.io)));
      } else if (result._typeId === MH.AwaitTypeId) {
        return T.map_(fiber.await, Ex.fold(cause => C.fromEffect(result.f(E.fold_(Cause.flipCauseEither(cause), _ => Ex.halt(_), _ => Ex.succeed(_)))), elem => zipRight_(C.write(elem), go(single(result.f)))));
      }

      throw new Error("Unexpected");
    }, elem => T.map_(T.fork(pull), leftFiber => zipRight_(C.write(elem), go(both(leftFiber, fiber)))));

    const go = state => {
      if (state._typeId === MH.BothRunningTypeId) {
        const lj = F.join(state.left);
        const rj = F.join(state.right);
        return C.unwrap(T.raceWith_(lj, rj, (leftEx, _) => handleSide(leftEx, state.right, pullL)(leftDone, (l, r) => new MH.BothRunning(l, r), _ => new MH.LeftDone(_)), (rightEx, _) => handleSide(rightEx, state.left, pullR)(rightDone, (l, r) => new MH.BothRunning(r, l), _ => new MH.RightDone(_))));
      } else if (state._typeId === MH.LeftDoneTypeId) {
        return C.unwrap(T.map_(T.result(pullR), Ex.fold(cause => C.fromEffect(state.f(E.fold_(Cause.flipCauseEither(cause), _ => Ex.halt(_), _ => Ex.succeed(_)))), elem => zipRight_(C.write(elem), go(new MH.LeftDone(state.f))))));
      } else {
        return C.unwrap(T.map_(T.result(pullL), Ex.fold(cause => C.fromEffect(state.f(E.fold_(Cause.flipCauseEither(cause), _ => Ex.halt(_), _ => Ex.succeed(_)))), elem => zipRight_(C.write(elem), go(new MH.RightDone(state.f))))));
      }
    };

    return C.embedInput_(C.chain_(C.fromEffect(T.zipWith_(T.fork(pullL), T.fork(pullR), (a, b) => new MH.BothRunning(a, b))), go), input);
  });
  return C.unwrapManaged(m);
}
/**
 * Returns a new channel, which is the merge of this channel and the specified channel, where
 * the behavior of the returned channel on left or right early termination is decided by the
 * specified `leftDone` and `rightDone` merge decisions.
 *
 * @ets_data_first mergeWith_
 */

export function mergeWith(that, leftDone, rightDone) {
  return self => mergeWith_(self, that, leftDone, rightDone);
}
/**
 * Maps the output of this channel using f
 */

export function mapOut_(self, f) {
  const reader = C.readWith(i => C.chain_(C.write(f(i)), () => reader), C.fail, C.end);
  return self[">>>"](reader);
}
/**
 * Maps the output of this channel using f
 *
 * @ets_data_first mapOut_
 */

export function mapOut(f) {
  return self => mapOut_(self, f);
}

const mapOutMReader = f => C.readWith(out => C.chain_(C.fromEffect(f(out)), _ => zipRight_(C.write(_), mapOutMReader(f))), e => C.fail(e), z => C.end(z));

export function mapOutEffect_(self, f) {
  return C.pipeTo_(self, mapOutMReader(f));
}
/**
 * @ets_data_first mapOutEffect_
 */

export function mapOutEffect(f) {
  return self => mapOutEffect_(self, f);
}
export const never = /*#__PURE__*/C.fromEffect(T.never);
export function orDie_(self, err) {
  return orDieWith_(self, _ => err);
}
/**
 * @ets_data_first orDie_
 */

export function orDie(err) {
  return self => orDie_(self, err);
}
export function orDieWith_(self, f) {
  return catchAll_(self, e => C.die(f(e)));
}
/**
 * @ets_data_first orDieWith_
 */

export function orDieWith(f) {
  return self => orDieWith_(self, f);
}
/**
 * Repeats this channel forever
 */

export function repeated(self) {
  return C.chain_(self, () => repeated(self));
}
/**
 * Runs a channel until the end is received
 */

export function runManaged(self) {
  return M.mapM_(M.makeExit_(T.succeedWith(() => new ChannelExecutor(() => self, undefined)), (exec, exit) => exec.close(exit) || T.unit), exec => T.suspend(() => runManagedInterpret(exec.run(), exec)));
}
/**
 * Runs a channel until the end is received
 */

export function run(self) {
  return M.useNow(runManaged(self));
}
export function runCollect(self) {
  return run(doneCollect(self));
}
/**
 * Runs a channel until the end is received
 */

export function runDrain(self) {
  return run(C.drain(self));
}
export function unit_(self) {
  return as_(self, undefined);
}
/**
 * Interpret a channel to a managed Pull
 */

export function toPull(self) {
  return M.map_(M.makeExit_(T.succeedWith(() => new ChannelExecutor(() => self, undefined)), (exec, exit) => exec.close(exit) || T.unit), exec => T.suspend(() => toPullInterpret(exec.run(), exec)));
}
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with a tuple of the terminal values of both channels.
 */

export function zip_(self, that) {
  return C.chain_(self, z => map_(that, z2 => Tp.tuple(z, z2)));
}
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with a tuple of the terminal values of both channels.
 *
 * @ets_data_first zip_
 */

export function zip(that) {
  return self => zip_(self, that);
}
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of this channel.
 */

export function zipLeft_(self, that) {
  return map_(zip_(self, that), Tp.get(0));
}
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of this channel.
 *
 * @ets_data_first zipLeft_
 */

export function zipLeft(that) {
  return self => zipLeft_(self, that);
}
export function zipPar_(self, that) {
  return mergeWith_(self, that, exit1 => MH.await_(exit2 => T.done(Ex.zip_(exit1, exit2))), exit2 => MH.await_(exit1 => T.done(Ex.zip_(exit1, exit2))));
}
/**
 * @ets_data_first zipPar_
 */

export function zipPar(that) {
  return self => zipPar_(self, that);
}
export function zipParLeft_(self, that) {
  return map_(zipPar_(self, that), Tp.get(0));
}
/**
 * @ets_data_first zipParLeft_
 */

export function zipParLeft(that) {
  return self => zipParLeft_(self, that);
}
export function zipParRight_(self, that) {
  return map_(zipPar_(self, that), Tp.get(1));
}
/**
 * @ets_data_first zipParRight_
 */

export function zipParRight(that) {
  return self => zipParRight_(self, that);
}
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of the other channel.
 */

export function zipRight_(self, that) {
  return map_(zip_(self, that), Tp.get(1));
}
/**
 * Returns a new channel that is the sequential composition of this channel and the specified
 * channel. The returned channel terminates with the terminal value of the other channel.
 *
 * @ets_data_first zipRight_
 */

export function zipRight(that) {
  return self => zipRight_(self, that);
}
export function bracketOut_(acquire, release) {
  return C.bracketOutExit_(acquire, (z, _) => release(z));
}
/**
 * @ets_data_first bracketOut_
 */

export function bracketOut(release) {
  return acquire => bracketOut_(acquire, release);
}
export function bracket_(acquire, use, release) {
  return bracketExit_(acquire, use, (a, _) => release(a));
}
/**
 * @ets_data_first bracket_
 */

export function bracket(use, release) {
  return acquire => bracket_(acquire, use, release);
}
export function bracketExit_(acquire, use, release) {
  return C.chain_(C.fromEffect(Ref.makeRef(_ => T.unit)), ref => C.ensuringWith_(C.chain_(C.fromEffect(T.uninterruptible(T.tap_(acquire, a => ref.set(_ => release(a, _))))), use), ex => T.chain_(ref.get, _ => _(ex))));
}
/**
 * @ets_data_first bracketExit_
 */

export function bracketExit(use, release) {
  return acquire => bracketExit_(acquire, use, release);
}
/**
 * Creates a channel backed by a buffer. When the buffer is empty, the channel will simply
 * passthrough its input as output. However, when the buffer is non-empty, the value inside
 * the buffer will be passed along as output.
 */

export function buffer(empty, isEmpty, ref) {
  return C.unwrap(Ref.modify_(ref, v => {
    if (isEmpty(v)) {
      return Tp.tuple(C.readWith(_in => zipRight_(C.write(_in), buffer(empty, isEmpty, ref)), err => C.fail(err), done => C.end(done)), v);
    } else {
      return Tp.tuple(zipRight_(C.write(v), buffer(empty, isEmpty, ref)), empty);
    }
  }));
}
export function bufferChunk(ref) {
  return buffer(A.empty(), _ => A.isEmpty(_), ref);
}
export function concatAll(channels) {
  return C.concatAllWith_(channels, (_, __) => void 0, (_, __) => void 0);
}
export function fromEither(either) {
  return E.fold_(either, C.fail, succeed);
}
export function fromOption(option) {
  return O.fold_(option, () => C.fail(O.none), _ => succeed(_));
}
export function identity() {
  return C.readWith(_in => zipRight_(C.write(_in), identity()), err => C.fail(err), done => C.end(done));
}
export function interrupt(fiberId) {
  return C.failCause(Cause.interrupt(fiberId));
}
export function managed_(m, use) {
  return bracket_(RM.makeReleaseMap, releaseMap => {
    return C.chain_(C.fromEffect(T.map_(T.provideSome_(m.effect, _ => Tp.tuple(_, releaseMap)), Tp.get(1))), use);
  }, _ => RM.releaseAll(Ex.unit, // FIXME: BracketOut should be BracketOutExit (From ZIO)
  sequential)(_));
}
/**
 * @ets_data_first managed_
 */

export function managed(use) {
  return m => managed_(m, use);
}
export function readOrFail(e) {
  return new P.Read(in_ => C.end(in_), new P.ContinuationK(_ => C.fail(e), _ => C.fail(e)));
}
export function read() {
  return readOrFail(O.none);
}
export function succeed(z) {
  return C.end(z);
}
export function fromHub(hub) {
  return managed_(H.subscribe(hub), fromQueue);
}
export function fromInput(input) {
  return C.unwrap(input.takeWith(_ => C.failCause(_), _ => zipRight_(C.write(_), fromInput(input)), _ => C.end(_)));
}
export function fromQueue(queue) {
  return C.chain_(C.fromEffect(Q.take(queue)), Ex.fold(cause => E.fold_(Cause.flipCauseEither(cause), cause => C.failCause(cause), done => C.end(done)), elem => zipRight_(C.write(elem), fromQueue(queue))));
}
export function toHub(hub) {
  return toQueue(H.toQueue(hub));
}
export function toQueue(queue) {
  return C.readWithCause(in_ => zipRight_(C.fromEffect(Q.offer_(queue, Ex.succeed(in_))), toQueue(queue)), cause => C.fromEffect(Q.offer_(queue, Ex.halt(Cause.map_(cause, _ => E.left(_))))), done => C.fromEffect(Q.offer_(queue, Ex.fail(E.right(done)))));
}
export function writeAll(...outs) {
  return AR.reduceRight_(outs, C.end(undefined), (out, conduit) => zipRight_(C.write(out), conduit));
}
export function writeChunk(outs) {
  const writer = (idx, len) => idx === len ? C.unit : zipRight_(C.write(A.unsafeGet_(outs, idx)), writer(idx + 1, len));

  return writer(0, A.size(outs));
}
//# sourceMappingURL=api.js.map