// src/compilerPlugin.ts
import ts6, { factory as factory4 } from "typescript";

// src/compilerPluginHelper.ts
import { factory } from "typescript";
import path from "path";
import process2 from "process";
import fs from "fs";
var getPatchedHost = (maybeHost, tsInstance, compilerOptions) => {
  const fileCache = /* @__PURE__ */ new Map();
  const compilerHost = maybeHost ?? tsInstance.createCompilerHost(compilerOptions, true);
  const originalGetSourceFile = compilerHost.getSourceFile;
  return Object.assign(compilerHost, {
    getSourceFile(fileName, languageVersion) {
      fileName = tsInstance.server.toNormalizedPath(fileName);
      if (fileCache.has(fileName)) return fileCache.get(fileName);
      const sourceFile = originalGetSourceFile.apply(
        void 0,
        Array.from(arguments)
      );
      fileCache.set(fileName, sourceFile);
      return sourceFile;
    },
    fileCache
  });
};
var isMooseFile = (sourceFile) => {
  const location = path.resolve(sourceFile.fileName);
  return location.includes("@514labs/moose-lib") || // workaround for e2e test
  location.includes("packages/ts-moose-lib/dist") || // support local development with symlinked packages
  location.includes("packages/ts-moose-lib/src");
};
var replaceProgram = (transform2) => (program, host, config, { ts: tsInstance }) => {
  const transformFunction = transform2(program.getTypeChecker());
  const compilerOptions = program.getCompilerOptions();
  const compilerHost = getPatchedHost(host, tsInstance, compilerOptions);
  const rootFileNames = program.getRootFileNames().map(tsInstance.server.toNormalizedPath);
  const transformedSource = tsInstance.transform(
    program.getSourceFiles().filter(
      (sourceFile) => (
        // relative path, or
        !sourceFile.fileName.startsWith("/") || // current directory but not in node_modules
        sourceFile.fileName.startsWith(`${process2.cwd()}`) && !sourceFile.fileName.startsWith(`${process2.cwd()}/node_modules`)
      )
    ),
    [transformFunction],
    compilerOptions
  ).transformed;
  const { printFile } = tsInstance.createPrinter();
  for (const sourceFile of transformedSource) {
    const { fileName, languageVersion } = sourceFile;
    const newFile = printFile(sourceFile);
    try {
      const path2 = fileName.split("/").pop() || fileName;
      const dir = `${process2.cwd()}/.moose/api-compile-step/`;
      fs.mkdirSync(dir, {
        recursive: true
      });
      fs.writeFileSync(`${dir}/${path2}`, newFile);
    } catch (e) {
    }
    const updatedSourceFile = tsInstance.createSourceFile(
      fileName,
      newFile,
      languageVersion
    );
    updatedSourceFile.version = sourceFile.version;
    compilerHost.fileCache.set(fileName, updatedSourceFile);
  }
  return tsInstance.createProgram(
    rootFileNames,
    compilerOptions,
    compilerHost
  );
};
var avoidTypiaNameClash = "____moose____typia";
var sanitizeTypeParameter = (typeNode) => factory.createImportTypeNode(
  factory.createLiteralTypeNode(
    factory.createStringLiteral("@514labs/moose-lib")
  ),
  void 0,
  factory.createIdentifier("StripDateIntersection"),
  [typeNode],
  false
);
var typiaJsonSchemas = (typeNode) => factory.createCallExpression(
  factory.createPropertyAccessExpression(
    factory.createPropertyAccessExpression(
      factory.createIdentifier(avoidTypiaNameClash),
      factory.createIdentifier("json")
    ),
    factory.createIdentifier("schemas")
  ),
  [factory.createTupleTypeNode([sanitizeTypeParameter(typeNode)])],
  []
);

// src/commons.ts
import { createClient } from "@clickhouse/client";
import { KafkaJS } from "@514labs/kafka-javascript";
var { Kafka } = KafkaJS;
function isTruthy(value) {
  if (!value) return false;
  switch (value.trim().toLowerCase()) {
    case "1":
    case "true":
    case "yes":
    case "on":
      return true;
    default:
      return false;
  }
}
var compilerLog = (message) => {
  if (!isTruthy(process.env.MOOSE_DISABLE_COMPILER_LOGS)) {
    console.log(message);
  }
};

// src/dmv2/dataModelMetadata.ts
import ts4, { factory as factory2 } from "typescript";

// src/dataModels/typeConvert.ts
import ts3, {
  displayPartsToString,
  isIdentifier,
  isTypeReferenceNode,
  SymbolFlags,
  TypeFlags
} from "typescript";

// src/dataModels/enumConvert.ts
import ts2 from "typescript";

// src/dataModels/dataModelTypes.ts
var UnknownType = class extends Error {
  t;
  fieldName;
  typeName;
  constructor(t, fieldName, typeName) {
    super();
    this.t = t;
    this.fieldName = fieldName;
    this.typeName = typeName;
  }
};
var NullType = class extends Error {
  fieldName;
  typeName;
  constructor(fieldName, typeName) {
    super();
    this.fieldName = fieldName;
    this.typeName = typeName;
  }
};
var UnsupportedEnum = class extends Error {
  enumName;
  constructor(enumName) {
    super();
    this.enumName = enumName;
  }
};
var UnsupportedFeature = class extends Error {
  featureName;
  constructor(featureName) {
    super();
    this.featureName = featureName;
  }
};
var IndexType = class extends Error {
  typeName;
  indexSignatures;
  constructor(typeName, indexSignatures) {
    const explanation = "Index signatures (e.g. [key: string]: value) are not supported in data models.";
    const suggestion = "Consider splitting this into separate types or using a single Record<K, V> type.";
    const signatures = `Found index signatures: ${indexSignatures.join(", ")}`;
    super(
      `${explanation}

Type: ${typeName}

${signatures}

Suggestion: ${suggestion}`
    );
    this.typeName = typeName;
    this.indexSignatures = indexSignatures;
  }
};

// src/dataModels/enumConvert.ts
var isEnum = (t) => !!(t.getFlags() & ts2.TypeFlags.EnumLiteral);
var enumConvert = (enumType) => {
  const name = enumType.symbol.name;
  const values = enumType.isUnion() ? (
    // an enum is the union of the values
    enumType.types
  ) : [enumType];
  const allStrings = values.every((v) => v.isStringLiteral());
  const allIntegers = values.every(
    (v) => v.isNumberLiteral() && Number.isInteger(v.value)
  );
  if (!allIntegers && !allStrings) {
    throw new UnsupportedEnum(name);
  }
  const enumMember = allStrings ? values.map((v) => ({
    name: v.symbol.name,
    value: { String: v.value }
  })) : values.map((v) => ({
    name: v.symbol.name,
    value: { Int: v.value }
  }));
  return { name, values: enumMember };
};

// src/dataModels/types.ts
var DecimalRegex = "^-?\\d+(\\.\\d+)?$";

// src/utilities/json.ts
var STRING_DATE_ANNOTATION = "stringDate";

// src/dataModels/typeConvert.ts
var dateType = (checker) => checker.getTypeOfSymbol(
  checker.resolveName("Date", void 0, SymbolFlags.Type, false)
).getConstructSignatures()[0].getReturnType();
var throwUnknownType = (t, fieldName, typeName) => {
  throw new UnknownType(t, fieldName, typeName);
};
var throwNullType = (fieldName, typeName) => {
  throw new NullType(fieldName, typeName);
};
var throwIndexTypeError = (t, checker) => {
  const interfaceName = t.symbol?.name || "unknown type";
  const indexInfos = checker.getIndexInfosOfType(t);
  const signatures = indexInfos.map((info) => {
    const keyType = checker.typeToString(info.keyType);
    const valueType = checker.typeToString(info.type);
    return `[${keyType}]: ${valueType}`;
  });
  throw new IndexType(interfaceName, signatures);
};
var getPropertyDeep = (t, name) => {
  const direct = t.getProperty(name);
  if (direct !== void 0) return direct;
  if (t.isIntersection()) {
    for (const sub of t.types) {
      const found = getPropertyDeep(sub, name);
      if (found) return found;
    }
  }
  return void 0;
};
var toArrayType = ([elementNullable, _, elementType]) => {
  return {
    elementNullable,
    elementType
  };
};
var isNumberType = (t, checker) => {
  return checker.isTypeAssignableTo(t, checker.getNumberType());
};
var handleAggregated = (t, checker, fieldName, typeName) => {
  const functionSymbol = t.getProperty("_aggregationFunction");
  const argsTypesSymbol = t.getProperty("_argTypes");
  if (functionSymbol === void 0 || argsTypesSymbol === void 0) {
    return void 0;
  }
  const functionStringLiteral = checker.getNonNullableType(
    checker.getTypeOfSymbol(functionSymbol)
  );
  const types = checker.getNonNullableType(
    checker.getTypeOfSymbol(argsTypesSymbol)
  );
  if (functionStringLiteral.isStringLiteral() && checker.isTupleType(types)) {
    const argumentTypes = (types.typeArguments || []).map(
      (argT) => {
        return tsTypeToDataType(argT, checker, fieldName, typeName, false)[2];
      }
    );
    return { functionName: functionStringLiteral.value, argumentTypes };
  } else {
    console.log(
      "[CompilerPlugin] Unexpected type inside Aggregated",
      functionStringLiteral
    );
    return void 0;
  }
};
var getTaggedType = (t, checker, propertyName) => {
  const nonNull = t.getNonNullableType();
  const ttlSymbol = nonNull.getProperty(propertyName);
  if (ttlSymbol === void 0) return null;
  return checker.getNonNullableType(checker.getTypeOfSymbol(ttlSymbol));
};
var getJsonMappedType = (t, checker) => {
  const mappingSymbol = getPropertyDeep(t, "_clickhouse_mapped_type");
  if (mappingSymbol === void 0) return null;
  const mappedType = checker.getNonNullableType(
    checker.getTypeOfSymbol(mappingSymbol)
  );
  if (!mappedType.isStringLiteral() || mappedType.value !== "JSON") {
    return null;
  }
  let maxDynamicPaths = void 0;
  let maxDynamicTypes = void 0;
  let skipPaths = [];
  let skipRegexes = [];
  const settingsSymbol = getPropertyDeep(t, "_clickhouse_json_settings");
  if (settingsSymbol !== void 0) {
    const settingsType = checker.getNonNullableType(
      checker.getTypeOfSymbol(settingsSymbol)
    );
    const maxPathsSymbol = getPropertyDeep(settingsType, "maxDynamicPaths");
    if (maxPathsSymbol !== void 0) {
      const maxPathsType = checker.getNonNullableType(
        checker.getTypeOfSymbol(maxPathsSymbol)
      );
      if (maxPathsType.isNumberLiteral()) {
        maxDynamicPaths = maxPathsType.value;
      }
    }
    const maxTypesSymbol = getPropertyDeep(settingsType, "maxDynamicTypes");
    if (maxTypesSymbol !== void 0) {
      const maxTypesType = checker.getNonNullableType(
        checker.getTypeOfSymbol(maxTypesSymbol)
      );
      if (maxTypesType.isNumberLiteral()) {
        maxDynamicTypes = maxTypesType.value;
      }
    }
    const skipPathsSymbol = getPropertyDeep(settingsType, "skipPaths");
    if (skipPathsSymbol !== void 0) {
      const skipPathsType = checker.getNonNullableType(
        checker.getTypeOfSymbol(skipPathsSymbol)
      );
      if (checker.isTupleType(skipPathsType)) {
        const tuple = skipPathsType;
        skipPaths = (tuple.typeArguments || []).filter((t2) => t2.isStringLiteral()).map((t2) => t2.value);
      }
    }
    const skipRegexesSymbol = getPropertyDeep(settingsType, "skipRegexes");
    if (skipRegexesSymbol !== void 0) {
      const skipRegexesType = checker.getNonNullableType(
        checker.getTypeOfSymbol(skipRegexesSymbol)
      );
      if (checker.isTupleType(skipRegexesType)) {
        const tuple = skipRegexesType;
        skipRegexes = (tuple.typeArguments || []).filter((t2) => t2.isStringLiteral()).map((t2) => t2.value);
      }
    }
  }
  let base = t.getNonNullableType();
  if (base.isIntersection()) {
    const candidates = base.types.filter((sub) => {
      const m = getPropertyDeep(sub, "_clickhouse_mapped_type");
      if (!m) return true;
      const mt = checker.getNonNullableType(checker.getTypeOfSymbol(m));
      return !(mt.isStringLiteral() && mt.value === "JSON");
    });
    if (candidates.length > 0) base = candidates[0];
  }
  let typedPaths = [];
  try {
    const cols = toColumns(base, checker);
    typedPaths = cols.map((c) => [c.name, c.data_type]);
  } catch (_) {
    typedPaths = [];
  }
  const hasAnyOption = typeof maxDynamicPaths === "number" || typeof maxDynamicTypes === "number" || typedPaths.length > 0 || skipPaths.length > 0 || skipRegexes.length > 0;
  if (!hasAnyOption) return "Json";
  const result = {
    typed_paths: typedPaths,
    skip_paths: skipPaths,
    skip_regexps: skipRegexes
  };
  if (typeof maxDynamicPaths === "number") {
    result.max_dynamic_paths = maxDynamicPaths;
  }
  if (typeof maxDynamicTypes === "number") {
    result.max_dynamic_types = maxDynamicTypes;
  }
  return result;
};
var handleSimpleAggregated = (t, checker, fieldName, typeName) => {
  const functionSymbol = t.getProperty("_simpleAggregationFunction");
  const argTypeSymbol = t.getProperty("_argType");
  if (functionSymbol === void 0 || argTypeSymbol === void 0) {
    return void 0;
  }
  const functionStringLiteral = checker.getNonNullableType(
    checker.getTypeOfSymbol(functionSymbol)
  );
  const argType = checker.getNonNullableType(
    checker.getTypeOfSymbol(argTypeSymbol)
  );
  if (functionStringLiteral.isStringLiteral()) {
    const argumentType = tsTypeToDataType(
      argType,
      checker,
      fieldName,
      typeName,
      false
    )[2];
    return { functionName: functionStringLiteral.value, argumentType };
  } else {
    console.log(
      "[CompilerPlugin] Unexpected type inside SimpleAggregated",
      functionStringLiteral
    );
    return void 0;
  }
};
var handleDefault = (t, checker) => {
  const defaultType = getTaggedType(t, checker, "_clickhouse_default");
  if (defaultType === null) {
    return null;
  }
  if (!defaultType.isStringLiteral()) {
    throw new UnsupportedFeature(
      'ClickHouseDefault must use a string literal, e.g. ClickHouseDefault<"now()">'
    );
  }
  return defaultType.value;
};
var handleMaterialized = (t, checker) => {
  const materializedType = getTaggedType(
    t,
    checker,
    "_clickhouse_materialized"
  );
  if (materializedType === null) {
    return null;
  }
  if (!materializedType.isStringLiteral()) {
    throw new UnsupportedFeature(
      'ClickHouseMaterialized must use a string literal, e.g. ClickHouseMaterialized<"toDate(timestamp)">'
    );
  }
  return materializedType.value;
};
var handleTtl = (t, checker) => {
  const ttlType = getTaggedType(t, checker, "_clickhouse_ttl");
  if (ttlType === null) {
    return null;
  }
  if (!ttlType.isStringLiteral()) {
    throw new UnsupportedFeature(
      'ClickHouseTTL must use a string literal, e.g. ClickHouseTTL<"timestamp + INTERVAL 1 WEEK">'
    );
  }
  return ttlType.value;
};
var handleNumberType = (t, checker, fieldName) => {
  const decimalPrecisionSymbol = getPropertyDeep(t, "_clickhouse_precision");
  const decimalScaleSymbol = getPropertyDeep(t, "_clickhouse_scale");
  if (decimalPrecisionSymbol !== void 0 && decimalScaleSymbol !== void 0) {
    const precisionType = checker.getNonNullableType(
      checker.getTypeOfSymbol(decimalPrecisionSymbol)
    );
    const scaleType = checker.getNonNullableType(
      checker.getTypeOfSymbol(decimalScaleSymbol)
    );
    if (precisionType.isNumberLiteral() && scaleType.isNumberLiteral()) {
      return `Decimal(${precisionType.value}, ${scaleType.value})`;
    }
  }
  const tagSymbol = t.getProperty("typia.tag");
  if (tagSymbol === void 0) {
    return "Float64";
  } else {
    const typiaProps = checker.getNonNullableType(
      checker.getTypeOfSymbol(tagSymbol)
    );
    const props = typiaProps.isIntersection() ? typiaProps.types : [typiaProps];
    for (const prop of props) {
      const valueSymbol = prop.getProperty("value");
      if (valueSymbol === void 0) {
        console.log(
          `[CompilerPlugin] Props.value is undefined for ${fieldName}`
        );
      } else {
        const valueTypeLiteral = checker.getTypeOfSymbol(valueSymbol);
        const numberTypeMappings = {
          float: "Float32",
          double: "Float64",
          int8: "Int8",
          int16: "Int16",
          int32: "Int32",
          int64: "Int64",
          uint8: "UInt8",
          uint16: "UInt16",
          uint32: "UInt32",
          uint64: "UInt64"
        };
        const match = Object.entries(numberTypeMappings).find(
          ([k, _]) => isStringLiteral(valueTypeLiteral, checker, k)
        );
        if (match) {
          return match[1];
        } else {
          const typeString = valueTypeLiteral.isStringLiteral() ? valueTypeLiteral.value : "unknown";
          console.log(
            `[CompilerPlugin] Other number types are not supported: ${typeString} in field ${fieldName}`
          );
        }
      }
    }
    return "Float64";
  }
};
var isStringLiteral = (t, checker, lit) => checker.isTypeAssignableTo(t, checker.getStringLiteralType(lit));
var handleStringType = (t, checker, fieldName, annotations) => {
  const fixedStringSizeSymbol = getPropertyDeep(
    t,
    "_clickhouse_fixed_string_size"
  );
  if (fixedStringSizeSymbol !== void 0) {
    const sizeType = checker.getNonNullableType(
      checker.getTypeOfSymbol(fixedStringSizeSymbol)
    );
    if (sizeType.isNumberLiteral()) {
      return `FixedString(${sizeType.value})`;
    }
  }
  const tagSymbol = t.getProperty("typia.tag");
  if (tagSymbol === void 0) {
    if (t.isUnion() && t.types.every((v) => v.isStringLiteral())) {
      annotations.push(["LowCardinality", true]);
    }
    return "String";
  } else {
    const typiaProps = checker.getNonNullableType(
      checker.getTypeOfSymbol(tagSymbol)
    );
    const props = typiaProps.isIntersection() ? typiaProps.types : [typiaProps];
    for (const prop of props) {
      const valueSymbol = prop.getProperty("value");
      if (valueSymbol === void 0) {
        console.log(
          `[CompilerPlugin] Props.value is undefined for ${fieldName}`
        );
      } else {
        const valueTypeLiteral = checker.getTypeOfSymbol(valueSymbol);
        if (isStringLiteral(valueTypeLiteral, checker, "uuid")) {
          return "UUID";
        } else if (isStringLiteral(valueTypeLiteral, checker, "date-time")) {
          let precision = 9;
          const precisionSymbol = t.getProperty("_clickhouse_precision");
          if (precisionSymbol !== void 0) {
            const precisionType = checker.getNonNullableType(
              checker.getTypeOfSymbol(precisionSymbol)
            );
            if (precisionType.isNumberLiteral()) {
              precision = precisionType.value;
            }
          }
          annotations.push([STRING_DATE_ANNOTATION, true]);
          return `DateTime(${precision})`;
        } else if (isStringLiteral(valueTypeLiteral, checker, "date")) {
          let size = 4;
          const sizeSymbol = t.getProperty("_clickhouse_byte_size");
          if (sizeSymbol !== void 0) {
            const sizeType = checker.getNonNullableType(
              checker.getTypeOfSymbol(sizeSymbol)
            );
            if (sizeType.isNumberLiteral()) {
              size = sizeType.value;
            }
          }
          if (size === 4) {
            return "Date";
          } else if (size === 2) {
            return "Date16";
          } else {
            throw new UnsupportedFeature(`Date with size ${size}`);
          }
        } else if (isStringLiteral(valueTypeLiteral, checker, "ipv4")) {
          return "IPv4";
        } else if (isStringLiteral(valueTypeLiteral, checker, "ipv6")) {
          return "IPv6";
        } else if (isStringLiteral(valueTypeLiteral, checker, DecimalRegex)) {
          let precision = 10;
          let scale = 0;
          const precisionSymbol = t.getProperty("_clickhouse_precision");
          if (precisionSymbol !== void 0) {
            const precisionType = checker.getNonNullableType(
              checker.getTypeOfSymbol(precisionSymbol)
            );
            if (precisionType.isNumberLiteral()) {
              precision = precisionType.value;
            }
          }
          const scaleSymbol = t.getProperty("_clickhouse_scale");
          if (scaleSymbol !== void 0) {
            const scaleType = checker.getNonNullableType(
              checker.getTypeOfSymbol(scaleSymbol)
            );
            if (scaleType.isNumberLiteral()) {
              scale = scaleType.value;
            }
          }
          return `Decimal(${precision}, ${scale})`;
        } else {
          const typeString = valueTypeLiteral.isStringLiteral() ? valueTypeLiteral.value : "unknown";
          console.log(
            `[CompilerPlugin] Unknown format: ${typeString} in field ${fieldName}`
          );
        }
      }
    }
    return "String";
  }
};
var isStringAnyRecord = (t, checker) => {
  const indexInfos = checker.getIndexInfosOfType(t);
  if (indexInfos && indexInfos.length === 1) {
    const indexInfo = indexInfos[0];
    return indexInfo.keyType == checker.getStringType() && indexInfo.type == checker.getAnyType();
  }
  return false;
};
var isRecordType = (t, checker) => {
  const indexInfos = checker.getIndexInfosOfType(t);
  return indexInfos && indexInfos.length === 1;
};
var isSingleUnderscoreMetaObject = (t, checker) => {
  const props = checker.getPropertiesOfType(t);
  if (props.length !== 1) return false;
  const onlyProp = props[0];
  const name = onlyProp.name;
  return typeof name === "string" && name.startsWith("_");
};
var handleRecordType = (t, checker, fieldName, typeName, isJwt) => {
  const indexInfos = checker.getIndexInfosOfType(t);
  if (indexInfos && indexInfos.length !== 1) {
    throwIndexTypeError(t, checker);
  }
  const indexInfo = indexInfos[0];
  const [, , keyType] = tsTypeToDataType(
    indexInfo.keyType,
    checker,
    `${fieldName}_key`,
    typeName,
    isJwt
  );
  const [, , valueType] = tsTypeToDataType(
    indexInfo.type,
    checker,
    `${fieldName}_value`,
    typeName,
    isJwt
  );
  return {
    keyType,
    valueType
  };
};
var isNamedTuple = (t, checker) => {
  const mappingSymbol = t.getProperty("_clickhouse_mapped_type");
  if (mappingSymbol === void 0) {
    return false;
  }
  return isStringLiteral(
    checker.getNonNullableType(checker.getTypeOfSymbol(mappingSymbol)),
    checker,
    "namedTuple"
  );
};
var getGeometryMappedType = (t, checker) => {
  const mappingSymbol = getPropertyDeep(t, "_clickhouse_mapped_type");
  if (mappingSymbol === void 0) return null;
  const mapped = checker.getNonNullableType(
    checker.getTypeOfSymbol(mappingSymbol)
  );
  const isPointTuple = (candidate) => {
    if (candidate.isIntersection()) {
      return candidate.types.some(isPointTuple);
    }
    if (!checker.isTupleType(candidate)) return false;
    const tuple = candidate;
    const args = tuple.typeArguments || [];
    if (args.length !== 2) return false;
    return isNumberType(args[0], checker) && isNumberType(args[1], checker);
  };
  const isArrayOf = (arrType, elementPredicate) => {
    if (arrType.isIntersection()) {
      return arrType.types.some((t2) => isArrayOf(t2, elementPredicate));
    }
    if (!checker.isArrayType(arrType)) return false;
    const elementType = arrType.getNumberIndexType();
    if (!elementType) return false;
    return elementPredicate(elementType);
  };
  const expectAndValidate = (shapeName, validator) => {
    if (!validator()) {
      throw new UnsupportedFeature(
        `Type annotated as ${shapeName} must be assignable to the expected geometry shape`
      );
    }
    return shapeName;
  };
  if (mapped.isStringLiteral()) {
    const v = mapped.value;
    switch (v) {
      case "Point":
        return expectAndValidate("Point", () => isPointTuple(t));
      case "Ring":
      case "LineString":
        return expectAndValidate(
          v,
          () => isArrayOf(t, (el) => isPointTuple(el))
        );
      case "MultiLineString":
      case "Polygon":
        return expectAndValidate(
          v,
          () => isArrayOf(t, (el) => isArrayOf(el, (inner) => isPointTuple(inner)))
        );
      case "MultiPolygon":
        return expectAndValidate(
          v,
          () => isArrayOf(
            t,
            (el) => isArrayOf(el, (inner) => isArrayOf(inner, isPointTuple))
          )
        );
    }
  }
  return null;
};
var checkColumnHasNoDefault = (c) => {
  if (c.default !== null) {
    throw new UnsupportedFeature(
      "Default in inner field. Put ClickHouseDefault in top level field."
    );
  }
};
var handleNested = (t, checker, fieldName, jwt) => {
  const columns = toColumns(t, checker);
  columns.forEach(checkColumnHasNoDefault);
  return {
    name: getNestedName(t, fieldName),
    columns,
    jwt
  };
};
var handleNamedTuple = (t, checker) => {
  return {
    fields: toColumns(t, checker).flatMap((c) => {
      if (c.name === "_clickhouse_mapped_type") return [];
      checkColumnHasNoDefault(c);
      const t2 = c.required ? c.data_type : { nullable: c.data_type };
      return [[c.name, t2]];
    })
  };
};
var tsTypeToDataType = (t, checker, fieldName, typeName, isJwt, typeNode) => {
  const nonNull = t.getNonNullableType();
  const nullable = nonNull != t;
  const aggregationFunction = handleAggregated(t, checker, fieldName, typeName);
  const simpleAggregationFunction = handleSimpleAggregated(
    t,
    checker,
    fieldName,
    typeName
  );
  let withoutTags = nonNull;
  if (nonNull.isIntersection()) {
    const nonTagTypes = nonNull.types.filter(
      (candidate) => !isSingleUnderscoreMetaObject(candidate, checker)
    );
    if (nonTagTypes.length == 1) {
      withoutTags = nonTagTypes[0];
    }
  }
  let datePrecisionFromNode = void 0;
  if (typeNode && isTypeReferenceNode(typeNode)) {
    const tn = typeNode.typeName;
    const name = isIdentifier(tn) ? tn.text : tn.right.text;
    if (name === "DateTime64") {
      const arg = typeNode.typeArguments?.[0];
      if (arg && ts3.isLiteralTypeNode(arg) && ts3.isNumericLiteral(arg.literal)) {
        datePrecisionFromNode = Number(arg.literal.text);
      }
    } else if (name === "DateTime") {
      datePrecisionFromNode = void 0;
    }
  }
  const annotations = [];
  const typeSymbolName = nonNull.symbol?.name || t.symbol?.name;
  const isDateLike = typeSymbolName === "DateTime" || typeSymbolName === "DateTime64" || checker.isTypeAssignableTo(nonNull, dateType(checker));
  let dataType;
  if (isEnum(nonNull)) {
    dataType = enumConvert(nonNull);
  } else {
    const jsonCandidate = getJsonMappedType(nonNull, checker);
    if (jsonCandidate !== null) {
      dataType = jsonCandidate;
    } else if (isStringAnyRecord(nonNull, checker)) {
      dataType = "Json";
    } else if (isDateLike) {
      if (datePrecisionFromNode !== void 0) {
        dataType = `DateTime(${datePrecisionFromNode})`;
      } else {
        const precisionSymbol = getPropertyDeep(nonNull, "_clickhouse_precision") || getPropertyDeep(t, "_clickhouse_precision");
        if (precisionSymbol !== void 0) {
          const precisionType = checker.getNonNullableType(
            checker.getTypeOfSymbol(precisionSymbol)
          );
          if (precisionType.isNumberLiteral()) {
            dataType = `DateTime(${precisionType.value})`;
          } else {
            dataType = "DateTime";
          }
        } else {
          dataType = "DateTime";
        }
      }
    } else if (checker.isTypeAssignableTo(nonNull, checker.getStringType())) {
      dataType = handleStringType(nonNull, checker, fieldName, annotations);
    } else if (isNumberType(nonNull, checker)) {
      dataType = handleNumberType(nonNull, checker, fieldName);
    } else if (checker.isTypeAssignableTo(nonNull, checker.getBooleanType())) {
      dataType = "Boolean";
    } else if (getGeometryMappedType(nonNull, checker) !== null) {
      dataType = getGeometryMappedType(nonNull, checker);
    } else if (checker.isArrayType(withoutTags)) {
      dataType = toArrayType(
        tsTypeToDataType(
          nonNull.getNumberIndexType(),
          checker,
          fieldName,
          typeName,
          isJwt,
          void 0
        )
      );
    } else if (isNamedTuple(nonNull, checker)) {
      dataType = handleNamedTuple(nonNull, checker);
    } else if (isRecordType(nonNull, checker)) {
      dataType = handleRecordType(nonNull, checker, fieldName, typeName, isJwt);
    } else if (withoutTags.isClassOrInterface() || (withoutTags.flags & TypeFlags.Object) !== 0) {
      dataType = handleNested(withoutTags, checker, fieldName, isJwt);
    } else if (nonNull == checker.getNeverType()) {
      dataType = throwNullType(fieldName, typeName);
    } else {
      dataType = throwUnknownType(t, fieldName, typeName);
    }
  }
  if (aggregationFunction !== void 0) {
    annotations.push(["aggregationFunction", aggregationFunction]);
  }
  if (simpleAggregationFunction !== void 0) {
    annotations.push(["simpleAggregationFunction", simpleAggregationFunction]);
  }
  const lowCardinalitySymbol = t.getProperty("_LowCardinality");
  if (lowCardinalitySymbol !== void 0) {
    const lowCardinalityType = checker.getNonNullableType(
      checker.getTypeOfSymbol(lowCardinalitySymbol)
    );
    if (lowCardinalityType == checker.getTrueType()) {
      annotations.push(["LowCardinality", true]);
    }
  }
  return [nullable, annotations, dataType];
};
var getNestedName = (t, fieldName) => {
  const name = t.symbol.name;
  return name === "__type" ? fieldName : name;
};
var hasWrapping = (typeNode, wrapperName) => {
  if (typeNode !== void 0 && isTypeReferenceNode(typeNode)) {
    const typeName = typeNode.typeName;
    const name = isIdentifier(typeName) ? typeName.text : typeName.right.text;
    return name === wrapperName && typeNode.typeArguments?.length === 1;
  } else {
    return false;
  }
};
var hasKeyWrapping = (typeNode) => {
  return hasWrapping(typeNode, "Key");
};
var hasJwtWrapping = (typeNode) => {
  return hasWrapping(typeNode, "JWT");
};
var handleDefaultWrapping = (typeNode) => {
  if (typeNode !== void 0 && isTypeReferenceNode(typeNode)) {
    const typeName = typeNode.typeName;
    const name = isIdentifier(typeName) ? typeName.text : typeName.right.text;
    if (name === "WithDefault" && typeNode.typeArguments?.length === 2) {
      const defaultValueType = typeNode.typeArguments[1];
      if (ts3.isLiteralTypeNode(defaultValueType) && ts3.isStringLiteral(defaultValueType.literal)) {
        return defaultValueType.literal.text;
      }
    }
  }
  return void 0;
};
var handleCodec = (t, checker) => {
  const codecType = getTaggedType(t, checker, "_clickhouse_codec");
  if (codecType === null) {
    return null;
  }
  if (!codecType.isStringLiteral()) {
    throw new UnsupportedFeature(
      'ClickHouseCodec must use a string literal, e.g. ClickHouseCodec<"ZSTD(3)">'
    );
  }
  return codecType.value;
};
var toColumns = (t, checker, options) => {
  if (!options?.allowIndexSignatures && checker.getIndexInfosOfType(t).length !== 0) {
    console.log("[CompilerPlugin]", checker.getIndexInfosOfType(t));
    throwIndexTypeError(t, checker);
  }
  return checker.getPropertiesOfType(t).map((prop) => {
    let declarations = prop.getDeclarations();
    const node = declarations && declarations.length > 0 ? declarations[0] : void 0;
    const type = node !== void 0 ? checker.getTypeOfSymbolAtLocation(prop, node) : checker.getTypeOfSymbol(prop);
    const isKey = hasKeyWrapping(node?.type);
    const isJwt = hasJwtWrapping(node?.type);
    const defaultExpression = handleDefaultWrapping(node?.type);
    const [nullable, annotations, dataType] = tsTypeToDataType(
      type,
      checker,
      prop.name,
      t.symbol?.name || "inline_type",
      isJwt,
      node?.type
    );
    const defaultValue = defaultExpression ?? handleDefault(type, checker);
    const materializedValue = handleMaterialized(type, checker);
    if (defaultValue && materializedValue) {
      throw new UnsupportedFeature(
        `Column '${prop.name}' cannot have both ClickHouseDefault and ClickHouseMaterialized. Use one or the other.`
      );
    }
    const docComment = prop.getDocumentationComment(checker);
    const comment = docComment.length > 0 ? displayPartsToString(docComment) : null;
    return {
      name: prop.name,
      data_type: dataType,
      primary_key: isKey,
      required: !nullable,
      unique: false,
      default: defaultValue,
      materialized: materializedValue,
      ttl: handleTtl(type, checker),
      codec: handleCodec(type, checker),
      annotations,
      comment
    };
  });
};

// src/dmv2/dataModelMetadata.ts
var typesToArgsLength = /* @__PURE__ */ new Map([
  ["OlapTable", 2],
  ["Stream", 2],
  ["DeadLetterQueue", 2],
  ["IngestPipeline", 2],
  ["IngestApi", 2],
  ["Api", 2],
  ["MaterializedView", 1],
  ["Task", 2]
]);
var isNewMooseResourceWithTypeParam = (node, checker) => {
  if (!ts4.isNewExpression(node)) {
    return false;
  }
  const declaration = checker.getResolvedSignature(node)?.declaration;
  if (!declaration || !isMooseFile(declaration.getSourceFile())) {
    return false;
  }
  const sym = checker.getSymbolAtLocation(node.expression);
  const typeName = sym?.name ?? "";
  if (!typesToArgsLength.has(typeName)) {
    return false;
  }
  return (
    // name only
    (node.arguments?.length === 1 || // config param
    node.arguments?.length === 2) && node.typeArguments?.length === 1
  );
};
var parseAsAny = (s) => factory2.createAsExpression(
  factory2.createCallExpression(
    factory2.createPropertyAccessExpression(
      factory2.createIdentifier("JSON"),
      factory2.createIdentifier("parse")
    ),
    void 0,
    [factory2.createStringLiteral(s)]
  ),
  factory2.createKeywordTypeNode(ts4.SyntaxKind.AnyKeyword)
);
var typiaTypeGuard = (node) => {
  const typeNode = node.typeArguments[0];
  return factory2.createCallExpression(
    factory2.createPropertyAccessExpression(
      factory2.createIdentifier(avoidTypiaNameClash),
      factory2.createIdentifier("createAssert")
    ),
    [sanitizeTypeParameter(typeNode)],
    []
  );
};
var transformNewMooseResource = (node, checker) => {
  const typeName = checker.getSymbolAtLocation(node.expression).name;
  const typeNode = node.typeArguments[0];
  let ingestPipelineHasTable = true;
  if (typeName === "IngestPipeline" && node.arguments && node.arguments.length >= 2) {
    const configArg = node.arguments[1];
    if (ts4.isObjectLiteralExpression(configArg)) {
      const tableProperty = configArg.properties.find(
        (prop) => ts4.isPropertyAssignment(prop) && ts4.isIdentifier(prop.name) && prop.name.text === "table"
      );
      if (tableProperty) {
        const tableValue = tableProperty.initializer;
        ingestPipelineHasTable = tableValue.kind !== ts4.SyntaxKind.FalseKeyword;
      }
    }
  }
  const allowIndexSignatures = ["IngestApi", "Stream"].includes(typeName) || typeName === "IngestPipeline" && !ingestPipelineHasTable;
  const typeAtLocation = checker.getTypeAtLocation(typeNode);
  const indexSignatures = checker.getIndexInfosOfType(typeAtLocation);
  const hasIndexSignature = allowIndexSignatures && indexSignatures.length > 0;
  if (typeName === "IngestPipeline" && ingestPipelineHasTable && indexSignatures.length > 0) {
    throw new Error(
      `IngestPipeline cannot use a type with index signatures when 'table' is configured. Extra fields would be silently dropped when writing to the ClickHouse table. Either:
  1. Remove the index signature from your type to use a fixed schema, or
  2. Set 'table: false' in your IngestPipeline config if you only need the API and stream`
    );
  }
  const internalArguments = typeName === "DeadLetterQueue" ? [typiaTypeGuard(node)] : [
    typiaJsonSchemas(typeNode),
    parseAsAny(
      JSON.stringify(
        toColumns(typeAtLocation, checker, {
          allowIndexSignatures
        })
      )
    )
  ];
  const resourceName = checker.getSymbolAtLocation(node.expression).name;
  const argLength = typesToArgsLength.get(resourceName);
  const needsExtraArg = node.arguments.length === argLength - 1;
  let updatedArgs = [
    ...node.arguments,
    ...needsExtraArg ? [factory2.createObjectLiteralExpression([], false)] : [],
    ...internalArguments
  ];
  if (resourceName === "OlapTable" || resourceName === "IngestPipeline") {
    const validatorsObject = factory2.createObjectLiteralExpression(
      [
        factory2.createPropertyAssignment(
          factory2.createIdentifier("validate"),
          createTypiaValidator(typeNode)
        ),
        factory2.createPropertyAssignment(
          factory2.createIdentifier("assert"),
          createTypiaAssert(typeNode)
        ),
        factory2.createPropertyAssignment(
          factory2.createIdentifier("is"),
          createTypiaIs(typeNode)
        )
      ],
      true
    );
    updatedArgs = [...updatedArgs, validatorsObject];
    if (resourceName === "IngestPipeline") {
      updatedArgs = [
        ...updatedArgs,
        hasIndexSignature ? factory2.createTrue() : factory2.createFalse()
      ];
    }
  }
  if (resourceName === "IngestApi" || resourceName === "Stream") {
    updatedArgs = [
      ...updatedArgs,
      factory2.createIdentifier("undefined"),
      // validators (not used for these types)
      hasIndexSignature ? factory2.createTrue() : factory2.createFalse()
    ];
  }
  return ts4.factory.updateNewExpression(
    node,
    node.expression,
    node.typeArguments,
    updatedArgs
  );
};
var createTypiaValidator = (typeNode) => {
  const typiaValidator = factory2.createCallExpression(
    factory2.createPropertyAccessExpression(
      factory2.createIdentifier(avoidTypiaNameClash),
      factory2.createIdentifier("createValidate")
    ),
    [sanitizeTypeParameter(typeNode)],
    []
  );
  return factory2.createArrowFunction(
    void 0,
    void 0,
    [
      factory2.createParameterDeclaration(
        void 0,
        void 0,
        factory2.createIdentifier("data"),
        void 0,
        factory2.createKeywordTypeNode(ts4.SyntaxKind.UnknownKeyword),
        void 0
      )
    ],
    void 0,
    factory2.createToken(ts4.SyntaxKind.EqualsGreaterThanToken),
    factory2.createBlock(
      [
        // const result = typiaValidator(data);
        factory2.createVariableStatement(
          void 0,
          factory2.createVariableDeclarationList(
            [
              factory2.createVariableDeclaration(
                factory2.createIdentifier("result"),
                void 0,
                void 0,
                factory2.createCallExpression(typiaValidator, void 0, [
                  factory2.createIdentifier("data")
                ])
              )
            ],
            ts4.NodeFlags.Const
          )
        ),
        // return { success: result.success, data: result.success ? result.data : undefined, errors: result.success ? undefined : result.errors };
        factory2.createReturnStatement(
          factory2.createObjectLiteralExpression(
            [
              factory2.createPropertyAssignment(
                factory2.createIdentifier("success"),
                factory2.createPropertyAccessExpression(
                  factory2.createIdentifier("result"),
                  factory2.createIdentifier("success")
                )
              ),
              factory2.createPropertyAssignment(
                factory2.createIdentifier("data"),
                factory2.createConditionalExpression(
                  factory2.createPropertyAccessExpression(
                    factory2.createIdentifier("result"),
                    factory2.createIdentifier("success")
                  ),
                  factory2.createToken(ts4.SyntaxKind.QuestionToken),
                  factory2.createPropertyAccessExpression(
                    factory2.createIdentifier("result"),
                    factory2.createIdentifier("data")
                  ),
                  factory2.createToken(ts4.SyntaxKind.ColonToken),
                  factory2.createIdentifier("undefined")
                )
              ),
              factory2.createPropertyAssignment(
                factory2.createIdentifier("errors"),
                factory2.createConditionalExpression(
                  factory2.createPropertyAccessExpression(
                    factory2.createIdentifier("result"),
                    factory2.createIdentifier("success")
                  ),
                  factory2.createToken(ts4.SyntaxKind.QuestionToken),
                  factory2.createIdentifier("undefined"),
                  factory2.createToken(ts4.SyntaxKind.ColonToken),
                  factory2.createPropertyAccessExpression(
                    factory2.createIdentifier("result"),
                    factory2.createIdentifier("errors")
                  )
                )
              )
            ],
            true
          )
        )
      ],
      true
    )
  );
};
var createTypiaAssert = (typeNode) => factory2.createCallExpression(
  factory2.createPropertyAccessExpression(
    factory2.createIdentifier(avoidTypiaNameClash),
    factory2.createIdentifier("createAssert")
  ),
  [sanitizeTypeParameter(typeNode)],
  []
);
var createTypiaIs = (typeNode) => factory2.createCallExpression(
  factory2.createPropertyAccessExpression(
    factory2.createIdentifier(avoidTypiaNameClash),
    factory2.createIdentifier("createIs")
  ),
  [sanitizeTypeParameter(typeNode)],
  []
);

// src/consumption-apis/typiaValidation.ts
import ts5, { factory as factory3, SyntaxKind } from "typescript";
var iife = (statements) => factory3.createCallExpression(
  factory3.createParenthesizedExpression(
    factory3.createArrowFunction(
      void 0,
      void 0,
      [],
      void 0,
      factory3.createToken(ts5.SyntaxKind.EqualsGreaterThanToken),
      factory3.createBlock(statements, true)
    )
  ),
  void 0,
  []
);
var isCreateApi = (node, checker) => {
  if (!ts5.isCallExpression(node)) {
    return false;
  }
  const declaration = checker.getResolvedSignature(node)?.declaration;
  if (!declaration || !isMooseFile(declaration.getSourceFile())) {
    return false;
  }
  return checker.getTypeAtLocation(declaration).symbol?.name == "createApi";
};
var isCreateApiV2 = (node, checker) => {
  if (!ts5.isNewExpression(node)) {
    return false;
  }
  const declaration = checker.getResolvedSignature(node)?.declaration;
  if (!declaration || !isMooseFile(declaration.getSourceFile())) {
    return false;
  }
  const sym = checker.getSymbolAtLocation(node.expression);
  return sym?.name === "Api" || sym?.name === "ConsumptionApi";
};
var getParamType = (funcType, checker) => {
  const sig = funcType.getCallSignatures()[0];
  const firstParam = sig && sig.getParameters()[0];
  const t = firstParam && checker.getTypeOfSymbol(firstParam);
  return t && checker.typeToTypeNode(t, void 0, void 0);
};
var typeToOutputSchema = (t, checker) => {
  if (t.isIntersection() && t.types.some((inner) => inner.getSymbol()?.name === "ResultSet")) {
    const queryResultSymbol = t.getProperty("__query_result_t");
    if (queryResultSymbol) {
      return checker.getNonNullableType(
        checker.getTypeOfSymbol(queryResultSymbol)
      );
    } else {
      return checker.getAnyType();
    }
  } else if (t.getProperty("status") !== void 0 && t.getProperty("body") !== void 0) {
    return checker.getTypeOfSymbol(t.getProperty("body"));
  } else {
    return t;
  }
};
var transformCreateApi = (node, checker) => {
  if (isCreateApi(node, checker)) {
    return transformLegacyApi(node, checker);
  } else if (isCreateApiV2(node, checker)) {
    return transformNewApi(node, checker);
  }
  return node;
};
var transformLegacyApi = (node, checker) => {
  if (!isCreateApi(node, checker)) {
    return node;
  }
  const handlerFunc = node.arguments[0];
  const paramType = node.typeArguments && node.typeArguments[0] || getParamType(checker.getTypeAtLocation(handlerFunc), checker);
  if (paramType === void 0) {
    throw new Error("Unknown type for params");
  }
  const handlerType = checker.getTypeAtLocation(handlerFunc);
  const returnType = handlerType.getCallSignatures()[0]?.getReturnType();
  const awaitedType = checker.getAwaitedType(returnType) || returnType;
  const queryResultType = awaitedType.isUnion() ? factory3.createUnionTypeNode(
    awaitedType.types.flatMap((t) => {
      const typeNode = checker.typeToTypeNode(
        typeToOutputSchema(t, checker),
        void 0,
        void 0
      );
      return typeNode === void 0 ? [] : [typeNode];
    })
  ) : checker.typeToTypeNode(
    typeToOutputSchema(awaitedType, checker),
    void 0,
    void 0
  );
  const wrappedFunc = factory3.createArrowFunction(
    void 0,
    void 0,
    [
      factory3.createParameterDeclaration(
        void 0,
        void 0,
        factory3.createIdentifier("params"),
        void 0,
        void 0,
        void 0
      ),
      factory3.createParameterDeclaration(
        void 0,
        void 0,
        factory3.createIdentifier("utils"),
        void 0,
        void 0,
        void 0
      )
    ],
    void 0,
    factory3.createToken(ts5.SyntaxKind.EqualsGreaterThanToken),
    factory3.createBlock(
      [
        factory3.createVariableStatement(
          void 0,
          factory3.createVariableDeclarationList(
            [
              factory3.createVariableDeclaration(
                factory3.createIdentifier("processedParams"),
                void 0,
                void 0,
                factory3.createCallExpression(
                  factory3.createIdentifier("assertGuard"),
                  void 0,
                  [
                    factory3.createNewExpression(
                      factory3.createIdentifier("URLSearchParams"),
                      void 0,
                      [factory3.createIdentifier("params")]
                    )
                  ]
                )
              )
            ],
            ts5.NodeFlags.Const
          )
        ),
        factory3.createReturnStatement(
          factory3.createCallExpression(
            factory3.createIdentifier("handlerFunc"),
            void 0,
            [
              factory3.createIdentifier("processedParams"),
              factory3.createIdentifier("utils")
            ]
          )
        )
      ],
      true
    )
  );
  return iife([
    // const assertGuard = ____moose____typia.http.createAssertQuery<T>()
    factory3.createVariableStatement(
      void 0,
      factory3.createVariableDeclarationList(
        [
          factory3.createVariableDeclaration(
            factory3.createIdentifier("assertGuard"),
            void 0,
            void 0,
            factory3.createCallExpression(
              factory3.createPropertyAccessExpression(
                factory3.createPropertyAccessExpression(
                  factory3.createIdentifier(avoidTypiaNameClash),
                  factory3.createIdentifier("http")
                ),
                factory3.createIdentifier("createAssertQuery")
              ),
              [sanitizeTypeParameter(paramType)],
              []
            )
          )
        ],
        ts5.NodeFlags.Const
      )
    ),
    // the user provided function
    // the Parameters of createApi is a trick to avoid extra imports
    // const handlerFunc: Parameters<typeof createApi<DailyActiveUsersParams>>[0] = async(...) => ...
    factory3.createVariableStatement(
      void 0,
      factory3.createVariableDeclarationList(
        [
          factory3.createVariableDeclaration(
            factory3.createIdentifier("handlerFunc"),
            void 0,
            factory3.createIndexedAccessTypeNode(
              factory3.createTypeReferenceNode(
                factory3.createIdentifier("Parameters"),
                [
                  factory3.createTypeQueryNode(
                    factory3.createIdentifier("createApi"),
                    [paramType]
                  )
                ]
              ),
              factory3.createLiteralTypeNode(factory3.createNumericLiteral("0"))
            ),
            handlerFunc
          )
        ],
        ts5.NodeFlags.Const
      )
    ),
    // const wrappedFunc = (params, utils) => {
    //   const processedParams = assertGuard(new URLSearchParams(params))
    //   return handlerFunc(params, utils)
    // }
    factory3.createVariableStatement(
      void 0,
      factory3.createVariableDeclarationList(
        [
          factory3.createVariableDeclaration(
            factory3.createIdentifier("wrappedFunc"),
            void 0,
            void 0,
            wrappedFunc
          )
        ],
        ts5.NodeFlags.Const
      )
    ),
    // wrappedFunc["moose_input_schema"] = ____moose____typia.json.schemas<[T]>()
    factory3.createExpressionStatement(
      factory3.createBinaryExpression(
        factory3.createElementAccessExpression(
          factory3.createIdentifier("wrappedFunc"),
          factory3.createStringLiteral("moose_input_schema")
        ),
        factory3.createToken(ts5.SyntaxKind.EqualsToken),
        typiaJsonSchemas(paramType)
      )
    ),
    // wrappedFunc["moose_output_schema"] = ____moose____typia.json.schemas<[Output]>()
    factory3.createExpressionStatement(
      factory3.createBinaryExpression(
        factory3.createElementAccessExpression(
          factory3.createIdentifier("wrappedFunc"),
          factory3.createStringLiteral("moose_output_schema")
        ),
        factory3.createToken(ts5.SyntaxKind.EqualsToken),
        factory3.createCallExpression(
          factory3.createPropertyAccessExpression(
            factory3.createPropertyAccessExpression(
              factory3.createIdentifier(avoidTypiaNameClash),
              factory3.createIdentifier("json")
            ),
            factory3.createIdentifier("schemas")
          ),
          [
            factory3.createTupleTypeNode([
              sanitizeTypeParameter(
                queryResultType || factory3.createKeywordTypeNode(ts5.SyntaxKind.AnyKeyword)
              )
            ])
          ],
          []
        )
      )
    ),
    factory3.createReturnStatement(factory3.createIdentifier("wrappedFunc"))
  ]);
};
var transformNewApi = (node, checker) => {
  if (!isCreateApiV2(node, checker)) {
    return node;
  }
  if (!node.arguments || node.arguments.length < 2 || !node.typeArguments) {
    return node;
  }
  const typeNode = node.typeArguments[0];
  const responseTypeNode = node.typeArguments[1] || factory3.createKeywordTypeNode(ts5.SyntaxKind.AnyKeyword);
  const handlerFunc = node.arguments[1];
  const wrappedHandler = factory3.createArrowFunction(
    void 0,
    void 0,
    [
      factory3.createParameterDeclaration(
        void 0,
        void 0,
        factory3.createIdentifier("params"),
        void 0,
        void 0,
        void 0
      ),
      factory3.createParameterDeclaration(
        void 0,
        void 0,
        factory3.createIdentifier("utils"),
        void 0,
        void 0,
        void 0
      )
    ],
    void 0,
    factory3.createToken(ts5.SyntaxKind.EqualsGreaterThanToken),
    factory3.createBlock(
      [
        // const assertGuard = ____moose____typia.http.createAssertQuery<T>()
        factory3.createVariableStatement(
          void 0,
          factory3.createVariableDeclarationList(
            [
              factory3.createVariableDeclaration(
                factory3.createIdentifier("assertGuard"),
                void 0,
                void 0,
                factory3.createCallExpression(
                  factory3.createPropertyAccessExpression(
                    factory3.createPropertyAccessExpression(
                      factory3.createIdentifier(avoidTypiaNameClash),
                      factory3.createIdentifier("http")
                    ),
                    factory3.createIdentifier("createAssertQuery")
                  ),
                  [typeNode],
                  []
                )
              )
            ],
            ts5.NodeFlags.Const
          )
        ),
        // const searchParams = new URLSearchParams(params as any)
        factory3.createVariableStatement(
          void 0,
          factory3.createVariableDeclarationList(
            [
              factory3.createVariableDeclaration(
                factory3.createIdentifier("searchParams"),
                void 0,
                void 0,
                factory3.createNewExpression(
                  factory3.createIdentifier("URLSearchParams"),
                  void 0,
                  [
                    factory3.createAsExpression(
                      factory3.createIdentifier("params"),
                      factory3.createKeywordTypeNode(ts5.SyntaxKind.AnyKeyword)
                    )
                  ]
                )
              )
            ],
            ts5.NodeFlags.Const
          )
        ),
        // const processedParams = assertGuard(searchParams)
        factory3.createVariableStatement(
          void 0,
          factory3.createVariableDeclarationList(
            [
              factory3.createVariableDeclaration(
                factory3.createIdentifier("processedParams"),
                void 0,
                void 0,
                factory3.createCallExpression(
                  factory3.createIdentifier("assertGuard"),
                  void 0,
                  [factory3.createIdentifier("searchParams")]
                )
              )
            ],
            ts5.NodeFlags.Const
          )
        ),
        factory3.createVariableStatement(
          void 0,
          factory3.createVariableDeclarationList(
            [
              factory3.createVariableDeclaration(
                factory3.createIdentifier("originalHandler"),
                void 0,
                factory3.createFunctionTypeNode(
                  void 0,
                  [
                    factory3.createParameterDeclaration(
                      void 0,
                      void 0,
                      "params",
                      void 0,
                      typeNode
                    ),
                    factory3.createParameterDeclaration(
                      void 0,
                      void 0,
                      "utils",
                      void 0,
                      factory3.createImportTypeNode(
                        factory3.createLiteralTypeNode(
                          factory3.createStringLiteral("@514labs/moose-lib")
                        ),
                        void 0,
                        factory3.createIdentifier("ApiUtil"),
                        [],
                        false
                      )
                    )
                  ],
                  factory3.createKeywordTypeNode(SyntaxKind.AnyKeyword)
                ),
                factory3.createParenthesizedExpression(handlerFunc)
              )
            ],
            ts5.NodeFlags.Const
          )
        ),
        // return originalHandler(processedParams, utils)
        factory3.createReturnStatement(
          factory3.createCallExpression(
            factory3.createIdentifier("originalHandler"),
            void 0,
            [
              factory3.createIdentifier("processedParams"),
              factory3.createIdentifier("utils")
            ]
          )
        )
      ],
      true
    )
  );
  const inputSchemaArg = node.arguments.length > 3 ? node.arguments[3] : typiaJsonSchemas(typeNode);
  const responseSchemaArg = typiaJsonSchemas(responseTypeNode);
  const inputColumnsArg = toColumns(
    checker.getTypeAtLocation(typeNode),
    checker
  );
  const configArg = node.arguments.length > 2 ? node.arguments[2] : factory3.createObjectLiteralExpression([], false);
  return factory3.updateNewExpression(
    node,
    node.expression,
    node.typeArguments,
    [
      node.arguments[0],
      // name
      wrappedHandler,
      // wrapped handler
      configArg,
      // config object
      inputSchemaArg,
      // input schema
      parseAsAny(JSON.stringify(inputColumnsArg)),
      // input columns
      responseSchemaArg
      // response schema
    ]
  );
};

// src/compilerPlugin.ts
var createTypiaImport = () => factory4.createImportDeclaration(
  void 0,
  factory4.createImportClause(
    false,
    factory4.createIdentifier(avoidTypiaNameClash),
    void 0
  ),
  factory4.createStringLiteral("typia"),
  void 0
);
var applyTransformation = (node, typeChecker) => {
  if (isCreateApi(node, typeChecker)) {
    compilerLog("[CompilerPlugin] Found legacy API, transforming...");
    return {
      transformed: transformLegacyApi(node, typeChecker),
      wasTransformed: true
    };
  }
  if (isCreateApiV2(node, typeChecker)) {
    compilerLog("[CompilerPlugin] Found API v2, transforming...");
    return {
      transformed: transformCreateApi(node, typeChecker),
      wasTransformed: true
    };
  }
  if (isNewMooseResourceWithTypeParam(node, typeChecker)) {
    compilerLog(
      "[CompilerPlugin] Found Moose resource with type param, transforming..."
    );
    return {
      transformed: transformNewMooseResource(node, typeChecker),
      wasTransformed: true
    };
  }
  return { transformed: node, wasTransformed: false };
};
var hasExistingTypiaImport = (sourceFile) => {
  const hasImport = sourceFile.statements.some((stmt) => {
    if (!ts6.isImportDeclaration(stmt) || !ts6.isStringLiteral(stmt.moduleSpecifier)) {
      return false;
    }
    if (stmt.moduleSpecifier.text !== "typia") {
      return false;
    }
    const importClause = stmt.importClause;
    if (importClause && importClause.name && importClause.name.text === avoidTypiaNameClash) {
      return true;
    }
    return false;
  });
  compilerLog(
    `[CompilerPlugin] Checking for existing typia import (${avoidTypiaNameClash}) in ${sourceFile.fileName}: ${hasImport}`
  );
  return hasImport;
};
var addTypiaImport = (sourceFile) => {
  if (hasExistingTypiaImport(sourceFile)) {
    compilerLog(
      `[CompilerPlugin] Typia import already exists in ${sourceFile.fileName}, skipping...`
    );
    return sourceFile;
  }
  compilerLog(`[CompilerPlugin] Adding typia import to ${sourceFile.fileName}`);
  const statementsWithImport = factory4.createNodeArray([
    createTypiaImport(),
    ...sourceFile.statements
  ]);
  return factory4.updateSourceFile(sourceFile, statementsWithImport);
};
var transform = (typeChecker) => (_context) => (sourceFile) => {
  compilerLog(
    `
[CompilerPlugin] ========== Processing file: ${sourceFile.fileName} ==========`
  );
  let transformationCount = 0;
  let hasTypiaTransformations = false;
  const visitNode = (node) => {
    const { transformed, wasTransformed } = applyTransformation(
      node,
      typeChecker
    );
    if (wasTransformed) {
      transformationCount++;
      hasTypiaTransformations = true;
      compilerLog(
        `[CompilerPlugin] Transformation #${transformationCount} applied at position ${node.pos}`
      );
    }
    return ts6.visitEachChild(transformed, visitNode, void 0);
  };
  const transformedSourceFile = ts6.visitEachChild(
    sourceFile,
    visitNode,
    void 0
  );
  compilerLog(
    `[CompilerPlugin] Total transformations applied: ${transformationCount}`
  );
  compilerLog(
    `[CompilerPlugin] Needs typia import: ${hasTypiaTransformations}`
  );
  if (hasTypiaTransformations) {
    const result = addTypiaImport(transformedSourceFile);
    compilerLog(
      `[CompilerPlugin] ========== Completed processing ${sourceFile.fileName} (with import) ==========
`
    );
    return result;
  } else {
    compilerLog(
      `[CompilerPlugin] ========== Completed processing ${sourceFile.fileName} (no import needed) ==========
`
    );
    return transformedSourceFile;
  }
};
var compilerPlugin_default = replaceProgram(transform);
export {
  createTypiaImport,
  compilerPlugin_default as default
};
//# sourceMappingURL=compilerPlugin.mjs.map