1import { memoize } from "../../Function.ts"
2import type * as Schema from "../../Schema.ts"
3import type * as SchemaAST from "../../SchemaAST.ts"
4
5/** @internal */
6export function resolve(ast: SchemaAST.AST): Schema.Annotations.Annotations | undefined {
7 return ast.checks ? ast.checks[ast.checks.length - 1].annotations : ast.annotations
8}
9
10/** @internal */
11export function resolveAt<A>(key: string) {
12 return (ast: SchemaAST.AST): A | undefined => resolve(ast)?.[key] as A | undefined
13}
14
15/** @internal */
16export const STRUCTURAL_ANNOTATION_KEY = "~structural"
17
18/** @internal */
19export const IDENTIFIER_FALLBACK_KEY = "~identifier"
20
21/** @internal */
22export const SENTINELS_ANNOTATION_KEY = "~sentinels"
23
24/** @internal */
25export const CONSTRUCTOR_ANNOTATION_KEY = "~constructor"
26
27/** @internal */
28export const jsonSchemaAnnotationKeys = [
29 "title",
30 "description",
31 "default",
32 "examples",
33 "readOnly",
34 "writeOnly",
35 "format",
36 "contentEncoding",
37 "contentMediaType",
38 "contentSchema"
39] as const
40
41/** @internal */
42export const resolveIdentifier = resolveAt<string>("identifier")
43
44/** @internal */
45export const resolveIdentifierFallback = resolveAt<string>(IDENTIFIER_FALLBACK_KEY)
46
47/** @internal */
48export const resolveTitle = resolveAt<string>("title")
49
50/** @internal */
51export const resolveDescription = resolveAt<string>("description")
52
53/** @internal */
54export const getExpected = memoize((ast: SchemaAST.AST): string => {
55 const identifier = resolve(ast)?.identifier
56 if (typeof identifier === "string") return identifier
57 return ast.getExpected(getExpected)
58})
59
60/** @internal */
61export const annotationExcludedKeys = new Set([
62 SENTINELS_ANNOTATION_KEY,
63 STRUCTURAL_ANNOTATION_KEY,
64 "representation",
65 "arbitraryConstraint",
66 "toJsonSchema",
67 "toCode",
68 "toEquivalence",
69 "toFormatter",
70 "toCodec",
71 "toCodecJson",
72 "toCodecStringTree",
73 "toCodecIso",
74 "toCodecArbitrary"
75])