import { TimedCache } from "../../../shared/src/cache.js";
import { getErrorMessage } from "../../../shared/src/error.js";
import { must } from "../../../shared/src/must.js";
import { transformResponseMessageSchema } from "../../../zero-protocol/src/custom-queries.js";
import { TransformFailed } from "../../../zero-protocol/src/error-kind-enum.js";
import { ZeroCache } from "../../../zero-protocol/src/error-origin-enum.js";
import { Internal } from "../../../zero-protocol/src/error-reason-enum.js";
import { isProtocolError } from "../../../zero-protocol/src/error.js";
import { hashOfAST } from "../../../zero-protocol/src/query-hash.js";
import { compileUrlPattern, fetchFromAPIServer } from "../custom/fetch.js";
class CustomQueryTransformer {
  #shard;
  #cache;
  #config;
  #urlPatterns;
  #lc;
  constructor(lc, config, shard) {
    this.#config = config;
    this.#shard = shard;
    this.#lc = lc;
    this.#urlPatterns = config.url.map(compileUrlPattern);
    this.#cache = new TimedCache(5e3);
  }
  async transform(headerOptions, queries, userQueryURL) {
    const request = [];
    const cachedResponses = [];
    if (!this.#config.forwardCookies && headerOptions.cookie) {
      headerOptions = {
        ...headerOptions,
        cookie: void 0
        // remove cookies if not forwarded
      };
    }
    for (const query of queries) {
      const cacheKey = getCacheKey(headerOptions, query.id);
      const cached = this.#cache.get(cacheKey);
      if (cached) {
        cachedResponses.push(cached);
      } else {
        request.push({
          id: query.id,
          name: query.name,
          args: query.args
        });
      }
    }
    if (request.length === 0) {
      return cachedResponses;
    }
    const queryIDs = request.map((r) => r.id);
    try {
      const transformResponse = await fetchFromAPIServer(
        transformResponseMessageSchema,
        "transform",
        this.#lc,
        userQueryURL ?? must(
          this.#config.url[0],
          "A ZERO_QUERY_URL must be configured for custom queries"
        ),
        this.#urlPatterns,
        this.#shard,
        headerOptions,
        ["transform", request]
      );
      if (transformResponse[0] === "transformFailed") {
        return transformResponse[1];
      }
      const newResponses = transformResponse[1].map((transformed) => {
        if ("error" in transformed) {
          return transformed;
        }
        return {
          id: transformed.id,
          transformedAst: transformed.ast,
          transformationHash: hashOfAST(transformed.ast)
        };
      });
      for (const transformed of newResponses) {
        if ("error" in transformed) {
          continue;
        }
        const cacheKey = getCacheKey(headerOptions, transformed.id);
        this.#cache.set(cacheKey, transformed);
      }
      return newResponses.concat(cachedResponses);
    } catch (e) {
      if (isProtocolError(e) && e.errorBody.kind === TransformFailed) {
        return {
          ...e.errorBody,
          queryIDs
        };
      }
      return {
        kind: TransformFailed,
        origin: ZeroCache,
        reason: Internal,
        message: `Failed to transform queries: ${getErrorMessage(e)}`,
        queryIDs
      };
    }
  }
}
function getCacheKey(headerOptions, queryID) {
  return `${headerOptions.token}:${headerOptions.cookie}:${queryID}`;
}
export {
  CustomQueryTransformer
};
//# sourceMappingURL=transform-query.js.map
