"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/index.ts
var _typescript = require('typescript'); var _typescript2 = _interopRequireDefault(_typescript);

// src/types.ts
var resolveOptions = (raw) => {
  const resolved = {
    nativeEnums: _optionalChain([raw, 'optionalAccess', _ => _.resolveNativeEnums]) ? "resolve" : "identifier"
  };
  return { ...resolved, ...raw };
};

// src/utils.ts

var { factory: f, SyntaxKind, ScriptKind, ScriptTarget, EmitHint } = _typescript2.default;
var maybeIdentifierToTypeReference = (identifier) => {
  if (_typescript2.default.isIdentifier(identifier)) {
    return f.createTypeReferenceNode(identifier);
  }
  return identifier;
};
var createTypeReferenceFromString = (identifier) => f.createTypeReferenceNode(f.createIdentifier(identifier));
var createUnknownKeywordNode = () => f.createKeywordTypeNode(SyntaxKind.UnknownKeyword);
var createTypeAlias = (node, identifier, comment) => {
  const typeAlias = f.createTypeAliasDeclaration(
    void 0,
    f.createIdentifier(identifier),
    void 0,
    node
  );
  if (comment) {
    addJsDocComment(typeAlias, comment);
  }
  return typeAlias;
};
var printNode = (node, printerOptions) => {
  const sourceFile = _typescript2.default.createSourceFile("print.ts", "", ScriptTarget.Latest, false, ScriptKind.TS);
  const printer = _typescript2.default.createPrinter(printerOptions);
  return printer.printNode(EmitHint.Unspecified, node, sourceFile);
};
var withGetType = (schema, getType) => {
  schema._def.getType = getType;
  return schema;
};
var identifierRE = /^[$A-Z_a-z][\w$]*$/;
var getIdentifierOrStringLiteral = (string_) => {
  if (identifierRE.test(string_)) {
    return f.createIdentifier(string_);
  }
  return f.createStringLiteral(string_);
};
var addJsDocComment = (node, text) => {
  _typescript2.default.addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, `* ${text} `, true);
};

// src/index.ts
var { factory: f2, SyntaxKind: SyntaxKind2 } = _typescript2.default;
var callGetType = (zod, identifier, options) => {
  let type;
  if (zod._def.getType)
    type = zod._def.getType(_typescript2.default, identifier, options);
  return type;
};
var zodToTs = (zod, identifier, options) => {
  const resolvedIdentifier = _nullishCoalesce(identifier, () => ( "Identifier"));
  const resolvedOptions = resolveOptions(options);
  const store = { nativeEnums: [] };
  const node = zodToTsNode(zod, resolvedIdentifier, store, resolvedOptions);
  return { node, store };
};
var zodToTsNode = (zod, identifier, store, options) => {
  const typeName = zod._def.typeName;
  const getTypeType = callGetType(zod, identifier, options);
  if (getTypeType && typeName !== "ZodNativeEnum") {
    return maybeIdentifierToTypeReference(getTypeType);
  }
  const otherArguments = [identifier, store, options];
  switch (typeName) {
    case "ZodString": {
      return f2.createKeywordTypeNode(SyntaxKind2.StringKeyword);
    }
    case "ZodNumber": {
      return f2.createKeywordTypeNode(SyntaxKind2.NumberKeyword);
    }
    case "ZodBigInt": {
      return f2.createKeywordTypeNode(SyntaxKind2.BigIntKeyword);
    }
    case "ZodBoolean": {
      return f2.createKeywordTypeNode(SyntaxKind2.BooleanKeyword);
    }
    case "ZodDate": {
      return f2.createTypeReferenceNode(f2.createIdentifier("Date"));
    }
    case "ZodUndefined": {
      return f2.createKeywordTypeNode(SyntaxKind2.UndefinedKeyword);
    }
    case "ZodNull": {
      return f2.createLiteralTypeNode(f2.createNull());
    }
    case "ZodVoid": {
      return f2.createUnionTypeNode([
        f2.createKeywordTypeNode(SyntaxKind2.VoidKeyword),
        f2.createKeywordTypeNode(SyntaxKind2.UndefinedKeyword)
      ]);
    }
    case "ZodAny": {
      return f2.createKeywordTypeNode(SyntaxKind2.AnyKeyword);
    }
    case "ZodUnknown": {
      return createUnknownKeywordNode();
    }
    case "ZodNever": {
      return f2.createKeywordTypeNode(SyntaxKind2.NeverKeyword);
    }
    case "ZodLazy": {
      if (!getTypeType)
        return createTypeReferenceFromString(identifier);
      break;
    }
    case "ZodLiteral": {
      let literal;
      const literalValue = zod._def.value;
      switch (typeof literalValue) {
        case "number": {
          literal = f2.createNumericLiteral(literalValue);
          break;
        }
        case "boolean": {
          literal = literalValue === true ? f2.createTrue() : f2.createFalse();
          break;
        }
        default: {
          literal = f2.createStringLiteral(literalValue);
          break;
        }
      }
      return f2.createLiteralTypeNode(literal);
    }
    case "ZodObject": {
      const properties = Object.entries(zod._def.shape());
      const members = properties.map(([key, value]) => {
        const nextZodNode = value;
        const type = zodToTsNode(nextZodNode, ...otherArguments);
        const { typeName: nextZodNodeTypeName } = nextZodNode._def;
        const isOptional = nextZodNodeTypeName === "ZodOptional" || nextZodNode.isOptional();
        const propertySignature = f2.createPropertySignature(
          void 0,
          getIdentifierOrStringLiteral(key),
          isOptional ? f2.createToken(SyntaxKind2.QuestionToken) : void 0,
          type
        );
        if (nextZodNode.description) {
          addJsDocComment(propertySignature, nextZodNode.description);
        }
        return propertySignature;
      });
      return f2.createTypeLiteralNode(members);
    }
    case "ZodArray": {
      const type = zodToTsNode(zod._def.type, ...otherArguments);
      const node = f2.createArrayTypeNode(type);
      return node;
    }
    case "ZodEnum": {
      const types = zod._def.values.map((value) => f2.createLiteralTypeNode(f2.createStringLiteral(value)));
      return f2.createUnionTypeNode(types);
    }
    case "ZodUnion": {
      const options2 = zod._def.options;
      const types = options2.map((option) => zodToTsNode(option, ...otherArguments));
      return f2.createUnionTypeNode(types);
    }
    case "ZodDiscriminatedUnion": {
      const options2 = [...zod._def.options.values()];
      const types = options2.map((option) => zodToTsNode(option, ...otherArguments));
      return f2.createUnionTypeNode(types);
    }
    case "ZodEffects": {
      const node = zodToTsNode(zod._def.schema, ...otherArguments);
      return node;
    }
    case "ZodNativeEnum": {
      const type = getTypeType;
      if (options.nativeEnums === "union") {
        if (type)
          return maybeIdentifierToTypeReference(type);
        const types = Object.values(zod._def.values).map((value) => {
          if (typeof value === "number") {
            return f2.createLiteralTypeNode(f2.createNumericLiteral(value));
          }
          return f2.createLiteralTypeNode(f2.createStringLiteral(value));
        });
        return f2.createUnionTypeNode(types);
      }
      if (!type)
        return createUnknownKeywordNode();
      if (options.nativeEnums === "resolve") {
        const enumMembers = Object.entries(zod._def.values).map(([key, value]) => {
          const literal = typeof value === "number" ? f2.createNumericLiteral(value) : f2.createStringLiteral(value);
          return f2.createEnumMember(
            getIdentifierOrStringLiteral(key),
            literal
          );
        });
        if (_typescript2.default.isIdentifier(type)) {
          store.nativeEnums.push(
            f2.createEnumDeclaration(
              void 0,
              type,
              enumMembers
            )
          );
        } else {
          throw new Error('getType on nativeEnum must return an identifier when nativeEnums is "resolve"');
        }
      }
      return maybeIdentifierToTypeReference(type);
    }
    case "ZodOptional": {
      const innerType = zodToTsNode(zod._def.innerType, ...otherArguments);
      return f2.createUnionTypeNode([
        innerType,
        f2.createKeywordTypeNode(SyntaxKind2.UndefinedKeyword)
      ]);
    }
    case "ZodNullable": {
      const innerType = zodToTsNode(zod._def.innerType, ...otherArguments);
      return f2.createUnionTypeNode([
        innerType,
        f2.createLiteralTypeNode(f2.createNull())
      ]);
    }
    case "ZodTuple": {
      const types = zod._def.items.map((option) => zodToTsNode(option, ...otherArguments));
      return f2.createTupleTypeNode(types);
    }
    case "ZodRecord": {
      const valueType = zodToTsNode(zod._def.valueType, ...otherArguments);
      const node = f2.createTypeLiteralNode([f2.createIndexSignature(
        void 0,
        [f2.createParameterDeclaration(
          void 0,
          void 0,
          f2.createIdentifier("x"),
          void 0,
          f2.createKeywordTypeNode(SyntaxKind2.StringKeyword)
        )],
        valueType
      )]);
      return node;
    }
    case "ZodMap": {
      const valueType = zodToTsNode(zod._def.valueType, ...otherArguments);
      const keyType = zodToTsNode(zod._def.keyType, ...otherArguments);
      const node = f2.createTypeReferenceNode(
        f2.createIdentifier("Map"),
        [
          keyType,
          valueType
        ]
      );
      return node;
    }
    case "ZodSet": {
      const type = zodToTsNode(zod._def.valueType, ...otherArguments);
      const node = f2.createTypeReferenceNode(
        f2.createIdentifier("Set"),
        [type]
      );
      return node;
    }
    case "ZodIntersection": {
      const left = zodToTsNode(zod._def.left, ...otherArguments);
      const right = zodToTsNode(zod._def.right, ...otherArguments);
      const node = f2.createIntersectionTypeNode([left, right]);
      return node;
    }
    case "ZodPromise": {
      const type = zodToTsNode(zod._def.type, ...otherArguments);
      const node = f2.createTypeReferenceNode(
        f2.createIdentifier("Promise"),
        [type]
      );
      return node;
    }
    case "ZodFunction": {
      const argumentTypes = zod._def.args._def.items.map((argument, index) => {
        const argumentType = zodToTsNode(argument, ...otherArguments);
        return f2.createParameterDeclaration(
          void 0,
          void 0,
          f2.createIdentifier(`args_${index}`),
          void 0,
          argumentType
        );
      });
      argumentTypes.push(
        f2.createParameterDeclaration(
          void 0,
          f2.createToken(SyntaxKind2.DotDotDotToken),
          f2.createIdentifier(`args_${argumentTypes.length}`),
          void 0,
          f2.createArrayTypeNode(createUnknownKeywordNode())
        )
      );
      const returnType = zodToTsNode(zod._def.returns, ...otherArguments);
      const node = f2.createFunctionTypeNode(
        void 0,
        argumentTypes,
        returnType
      );
      return node;
    }
    case "ZodDefault": {
      const type = zodToTsNode(zod._def.innerType, ...otherArguments);
      const filteredNodes = [];
      type.forEachChild((node) => {
        if (![SyntaxKind2.UndefinedKeyword].includes(node.kind)) {
          filteredNodes.push(node);
        }
      });
      type.types = filteredNodes;
      return type;
    }
  }
  return f2.createKeywordTypeNode(SyntaxKind2.AnyKeyword);
};





exports.createTypeAlias = createTypeAlias; exports.printNode = printNode; exports.withGetType = withGetType; exports.zodToTs = zodToTs;
