import * as S from "effect/Schema"; import type { AST } from "effect/SchemaAST"; const Description = Symbol.for("effect/annotation/Description"); export const isTag = >(tag: T["ast"]["_tag"]) => ((schema) => S.isSchema(schema) ? S.encodedSchema(schema).ast._tag === tag : schema._tag === tag) as { (schema: S.Schema): schema is T; (schema: AST): boolean; }; export const hasGenericAnnotation = (type: string) => (ast: AST | undefined) => { const description: string | undefined = ast?.annotations?.[ Description ] as string; return ( description && description?.startsWith(`${type}<`) && description?.endsWith(">") ); }; export const isNullishSchema = (schema: S.Schema) => isNullSchema(schema) || isUndefinedSchema(schema); export const isNullSchema = (schema: S.Schema) => schema.ast._tag === "Literal" && schema.ast.literal === null; export const isUndefinedSchema = isTag("UndefinedKeyword"); export const isBooleanSchema = isTag>("BooleanKeyword"); export const isStringSchema = isTag>("StringKeyword"); export const isNumberSchema = isTag>("NumberKeyword"); export const hasMapAnnotation = hasGenericAnnotation("Map"); export const isRecordLikeSchema = (schema: S.Schema) => isMapSchema(schema) || isRecordSchema(schema) || isStructSchema(schema) || isClassSchema(schema) || false; export const isMapSchema = (schema: S.Schema) => hasMapAnnotation(schema.ast) || // @ts-expect-error - ast.to?. is not narrowed, we don't care hasMapAnnotation(schema.ast.to) || false; export const isClassSchema = (schema: S.Schema) => { const encoded = S.encodedSchema(schema); return ( encoded.ast._tag === "TypeLiteral" && encoded.ast.propertySignatures !== undefined ); }; export const isStructSchema = (schema: S.Schema) => { return ( schema.ast._tag === "TypeLiteral" && schema.ast.propertySignatures !== undefined ); }; export const isRecordSchema = (schema: S.Schema) => { const encoded = S.encodedSchema(schema); return ( encoded.ast._tag === "TypeLiteral" && encoded.ast.indexSignatures?.[0] !== undefined ); }; export const isListSchema = (schema: S.Schema) => { return ( hasListAnnotation(schema.ast) || (S.encodedSchema(schema).ast._tag === "TupleType" && !isMapSchema(schema)) ); }; export const hasListAnnotation = (ast: AST | undefined) => { const description: string | undefined = ast?.annotations?.[ Description ] as string; return ( description && description?.startsWith("List<") && description?.endsWith(">") ); }; export const isSetSchema = (schema: S.Schema) => { return ( // @ts-expect-error - ast.to?. is not narrowed, we don't care hasSetAnnotation(schema.ast) || hasSetAnnotation(schema.ast.to) || false ); }; export const hasSetAnnotation = hasGenericAnnotation("Set"); export const getSetValueAST = (schema: S.Schema): AST => // @ts-expect-error - ast.to?. is not narrowed, we don't care isSetSchema(schema) && schema.ast.to?.typeParameters[0];