// src/gateway/client.ts
var DEFAULT_BASE_URL = "https://athena-db.com";
var DEFAULT_CLIENT = "railway_direct";
function parseResponseText(text) {
  if (!text) return null;
  try {
    return JSON.parse(text);
  } catch {
    return text;
  }
}
function normalizeHeaderValue(value) {
  return value ? value : void 0;
}
function buildHeaders(config, options) {
  const mergedStripNulls = options?.stripNulls ?? config.stripNulls ?? true;
  const finalClient = options?.client ?? config.client ?? DEFAULT_CLIENT;
  const finalApiKey = options?.apiKey ?? config.apiKey;
  const finalSupabaseUrl = options?.supabaseUrl ?? config.supabaseUrl;
  const finalSupabaseKey = options?.supabaseKey ?? config.supabaseKey;
  const finalPublishEvent = options?.publishEvent ?? config.publishEvent;
  const extraHeaders = {
    ...config.headers ?? {},
    ...options?.headers ?? {}
  };
  const headers = {
    "Content-Type": "application/json"
  };
  if (options?.userId ?? config.userId) {
    headers["X-User-Id"] = options?.userId ?? config.userId ?? "";
  }
  if (options?.companyId ?? config.companyId) {
    headers["X-Company-Id"] = options?.companyId ?? config.companyId ?? "";
  }
  if (options?.organizationId ?? config.organizationId) {
    headers["X-Organization-Id"] = options?.organizationId ?? config.organizationId ?? "";
  }
  if (finalClient) {
    headers["X-Athena-Client"] = finalClient;
  }
  if (typeof mergedStripNulls === "boolean") {
    headers["X-Strip-Nulls"] = mergedStripNulls ? "true" : "false";
  }
  if (finalPublishEvent) {
    headers["X-Publish-Event"] = finalPublishEvent;
  }
  if (finalApiKey) {
    headers["apikey"] = finalApiKey;
    headers["x-api-key"] = headers["x-api-key"] ?? finalApiKey;
  }
  if (finalSupabaseUrl) {
    headers["x-supabase-url"] = finalSupabaseUrl;
  }
  if (finalSupabaseKey) {
    headers["x-supabase-key"] = finalSupabaseKey;
  }
  Object.entries(extraHeaders).forEach(([key, value]) => {
    const normalized = normalizeHeaderValue(value);
    if (normalized) {
      headers[key] = normalized;
    }
  });
  return headers;
}
async function callAthena(config, endpoint, method, payload, options) {
  const baseUrl = (options?.baseUrl ?? config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
  const url = `${baseUrl}${endpoint}`;
  const headers = buildHeaders(config, options);
  try {
    const response = await fetch(url, {
      method,
      headers,
      body: JSON.stringify(payload)
    });
    const rawText = await response.text();
    const parsed = parseResponseText(rawText ?? "");
    const parsedPayload = parsed;
    const parsedError = parsedPayload && typeof parsedPayload === "object" ? parsedPayload.error ?? parsedPayload.message : void 0;
    const hasError = typeof parsedError === "string" && parsedError.length > 0 ? parsedError : void 0;
    return {
      ok: response.ok,
      status: response.status,
      data: parsed ?? null,
      error: hasError,
      raw: parsed
    };
  } catch (callError) {
    const message = callError instanceof Error ? callError.message : String(callError);
    return {
      ok: false,
      status: 0,
      data: null,
      error: message,
      raw: null
    };
  }
}
function createAthenaGatewayClient(config = {}) {
  return {
    baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
    buildHeaders(options) {
      return buildHeaders(config, options);
    },
    fetchGateway(payload, options) {
      return callAthena(config, "/gateway/fetch", "POST", payload, options);
    },
    insertGateway(payload, options) {
      return callAthena(config, "/gateway/insert", "PUT", payload, options);
    },
    updateGateway(payload, options) {
      return callAthena(config, "/gateway/update", "POST", payload, options);
    },
    deleteGateway(payload, options) {
      return callAthena(config, "/gateway/delete", "DELETE", payload, options);
    }
  };
}

// src/supabase.ts
var DEFAULT_COLUMNS = "*";
function formatResult(response) {
  return {
    data: response.data ?? null,
    error: response.error ?? null,
    status: response.status,
    raw: response.raw
  };
}
function toSingleResult(response) {
  const payload = response.data;
  const singleData = Array.isArray(payload) ? payload.length ? payload[0] : null : payload ?? null;
  return {
    ...response,
    data: singleData
  };
}
function mergeOptions(...options) {
  return options.reduce((acc, next) => {
    if (!next) return acc;
    return { ...acc, ...next };
  }, void 0);
}
function createMutationQuery(executor, defaultColumns = DEFAULT_COLUMNS) {
  let selectedColumns = defaultColumns;
  let selectedOptions;
  let promise = null;
  const run = (columns, options) => {
    const payloadColumns = columns ?? selectedColumns;
    const payloadOptions = options ?? selectedOptions;
    if (!promise) {
      promise = executor(payloadColumns, payloadOptions);
    }
    return promise;
  };
  const mutationQuery = {
    select(columns = selectedColumns, options) {
      selectedColumns = columns;
      selectedOptions = options ?? selectedOptions;
      return run(columns, options);
    },
    returning(columns = selectedColumns, options) {
      return mutationQuery.select(columns, options);
    },
    single(columns = selectedColumns, options) {
      selectedColumns = columns;
      selectedOptions = options ?? selectedOptions;
      return run(columns, options).then(toSingleResult);
    },
    maybeSingle(columns = selectedColumns, options) {
      return mutationQuery.single(columns, options);
    },
    then(onfulfilled, onrejected) {
      return run(selectedColumns, selectedOptions).then(onfulfilled, onrejected);
    },
    catch(onrejected) {
      return run(selectedColumns, selectedOptions).catch(onrejected);
    },
    finally(onfinally) {
      return run(selectedColumns, selectedOptions).finally(onfinally);
    }
  };
  return mutationQuery;
}
function getResourceId(state) {
  const candidate = state.conditions.find(
    (condition) => condition.operator === "eq" && (condition.column === "resource_id" || condition.column === "id")
  );
  return candidate?.value?.toString();
}
function stringifyFilterValue(value) {
  if (Array.isArray(value)) {
    return value.join(",");
  }
  return String(value);
}
function createTableBuilder(tableName, client) {
  const state = {
    conditions: []
  };
  const addCondition = (operator, column, value) => {
    const condition = { operator };
    if (column) condition.column = column;
    if (value !== void 0) condition.value = value;
    state.conditions.push(condition);
  };
  const builder = {
    reset() {
      state.conditions = [];
      state.limit = void 0;
      state.offset = void 0;
      return builder;
    },
    range(from, to) {
      state.offset = from;
      state.limit = to - from + 1;
      return builder;
    },
    limit(count) {
      state.limit = count;
      return builder;
    },
    offset(count) {
      state.offset = count;
      return builder;
    },
    match(filters) {
      Object.entries(filters).forEach(([column, value]) => {
        addCondition("eq", column, value);
      });
      return builder;
    },
    eq(column, value) {
      addCondition("eq", column, value);
      return builder;
    },
    gt(column, value) {
      addCondition("gt", column, value);
      return builder;
    },
    gte(column, value) {
      addCondition("gte", column, value);
      return builder;
    },
    lt(column, value) {
      addCondition("lt", column, value);
      return builder;
    },
    lte(column, value) {
      addCondition("lte", column, value);
      return builder;
    },
    neq(column, value) {
      addCondition("neq", column, value);
      return builder;
    },
    like(column, value) {
      addCondition("like", column, value);
      return builder;
    },
    ilike(column, value) {
      addCondition("ilike", column, value);
      return builder;
    },
    is(column, value) {
      addCondition("is", column, value);
      return builder;
    },
    in(column, values) {
      addCondition("in", column, values);
      return builder;
    },
    contains(column, values) {
      addCondition("contains", column, values);
      return builder;
    },
    containedBy(column, values) {
      addCondition("containedBy", column, values);
      return builder;
    },
    not(columnOrExpression, operator, value) {
      if (operator && value !== void 0) {
        addCondition("not", void 0, `${columnOrExpression}.${operator}.${stringifyFilterValue(value)}`);
      } else {
        addCondition("not", void 0, columnOrExpression);
      }
      return builder;
    },
    or(expression) {
      addCondition("or", void 0, expression);
      return builder;
    },
    async select(columns = DEFAULT_COLUMNS, options) {
      const payload = {
        table_name: tableName,
        columns,
        conditions: state.conditions.length ? [...state.conditions] : void 0,
        limit: state.limit,
        offset: state.offset,
        strip_nulls: options?.stripNulls ?? true
      };
      const response = await client.fetchGateway(payload, options);
      return formatResult(response);
    },
    insert(values, options) {
      const executeInsert = async (columns, selectOptions) => {
        const mergedOptions = mergeOptions(options, selectOptions);
        const payload = {
          table_name: tableName,
          insert_body: values
        };
        if (columns) payload.columns = columns;
        if (mergedOptions?.count) payload.count = mergedOptions.count;
        if (mergedOptions?.head) payload.head = mergedOptions.head;
        if (mergedOptions?.defaultToNull !== void 0) {
          payload.default_to_null = mergedOptions.defaultToNull;
        }
        const response = await client.insertGateway(payload, mergedOptions);
        return formatResult(response);
      };
      return createMutationQuery(executeInsert);
    },
    upsert(values, options) {
      const executeUpsert = async (columns, selectOptions) => {
        const mergedOptions = mergeOptions(options, selectOptions);
        const payload = {
          table_name: tableName,
          insert_body: values,
          update_body: options?.updateBody ? options.updateBody : void 0
        };
        if (columns) payload.columns = columns;
        if (options?.onConflict) payload.on_conflict = options.onConflict;
        if (mergedOptions?.count) payload.count = mergedOptions.count;
        if (mergedOptions?.head) payload.head = mergedOptions.head;
        if (mergedOptions?.defaultToNull !== void 0) {
          payload.default_to_null = mergedOptions.defaultToNull;
        }
        const response = await client.insertGateway(payload, mergedOptions);
        return formatResult(response);
      };
      return createMutationQuery(executeUpsert);
    },
    update(values, options) {
      const filters = state.conditions.length ? [...state.conditions] : void 0;
      const executeUpdate = async (columns, selectOptions) => {
        const mergedOptions = mergeOptions(options, selectOptions);
        const payload = {
          table_name: tableName,
          update_body: values,
          conditions: filters,
          columns,
          strip_nulls: mergedOptions?.stripNulls ?? true
        };
        const response = await client.updateGateway(payload, mergedOptions);
        return formatResult(response);
      };
      return createMutationQuery(executeUpdate);
    },
    delete(options) {
      const filters = state.conditions.length ? [...state.conditions] : void 0;
      const resourceId = options?.resourceId ?? getResourceId(state);
      if (!resourceId && !filters?.length) {
        throw new Error('delete requires a resource_id either via eq("resource_id", ...) or options.resourceId');
      }
      const executeDelete = async (columns, selectOptions) => {
        const mergedOptions = mergeOptions(options, selectOptions);
        const payload = {
          table_name: tableName,
          resource_id: resourceId,
          conditions: filters,
          columns
        };
        const response = await client.deleteGateway(payload, mergedOptions);
        return formatResult(response);
      };
      return createMutationQuery(executeDelete);
    },
    async single(columns, options) {
      const response = await builder.select(columns, options);
      return toSingleResult(response);
    },
    async maybeSingle(columns, options) {
      return builder.single(columns, options);
    }
  };
  return builder;
}
function createClient(url, apiKey, options) {
  const { baseUrl: optBaseUrl, apiKey: optApiKey, ...restOptions } = options ?? {};
  const client = createAthenaGatewayClient({
    baseUrl: optBaseUrl ?? url,
    apiKey: optApiKey ?? apiKey,
    ...restOptions
  });
  return {
    from(table) {
      return createTableBuilder(table, client);
    }
  };
}

export { createClient };
//# sourceMappingURL=index.mjs.map
//# sourceMappingURL=index.mjs.map