/** * start of every record is: * @format $start = `[name?] [ttl?] IN _TYPE_ ` */ import { ParsedTypings } from '../shared/types_domain_specific'; import { InstructionType, ErrorKeyKind, DirectiveKind, } from '../shared/constants_domain_specific'; /** * @note ParsingRecordDataType + ClientRecordType & ApiRecordType * @description parts of a resource record being-parsed or already parsed */ export interface ParsingRecordDataType { tokens: string[]; values: string[]; name: string; /** nested parsing */ previousName: string; ttl?: number; } export interface Common { /** directive or record type */ instructionType: unknown; /** usually a string */ value: unknown; /** raw input */ lineContent: string; /** actual error */ error?: unknown; /** ErrorKeyKind */ errorType?: string; } namespace Internals { type SOA = Common & { instructionType: 'SOA'; value: ParsedTypings.Obj['SOA']; }; type Records = { SOA: SOA } & { [Key in InputTypings.SupportedRecordType]: Common & { instructionType: Key; value: ParsedTypings.ByType[Key]; }; }; interface TimeToLive extends Common { instructionType: DirectiveKind.TimeToLive; value: number; errorType: | ErrorKeyKind.TtlInvalidFormat | ErrorKeyKind.TtlOverflow | ErrorKeyKind.TtlMissingDefault; } interface Origin extends Common { instructionType: DirectiveKind.Origin; value: string; } type Directives = { [DirectiveKind.TimeToLive]: TimeToLive; [DirectiveKind.Origin]: Origin; }; type Problems = { [Key in ErrorKeyKind]: Common & { instructionType: Key; value: string; }; }; export type Indexed = Directives & Problems & Records; } /** import zone file text input */ export namespace InputTypings { /** supported by the parser */ export type SupportedRecordType = | 'TXT' | 'NS' | 'A' | 'AAAA' | 'CNAME' | 'MX' | 'PTR' | 'SPF' | 'SRV' | 'CAA' | 'NAPTR'; /** @desc a directive or a record - the beginning of a line */ export type Instruction = InstructionType; /** @note currently unused, here for future possible usage */ export type FileFormatVariations = | ['name', 'ttl', 'class', 'type', 'data'] | ['ttl', 'class', 'type', 'data'] | ['class', 'type', 'data']; } export namespace SourceMapTypings { export type Value = Internals.Indexed[keyof Internals.Indexed]; /** @example type Store = Map */ export interface Store extends Map { has(key: number): boolean; get( key: number ): Internals.Indexed[Instruction] | undefined; set( key: number, value: Internals.Indexed[Instruction] ): this; } } export namespace ParserTypings { export interface Parser { zoneObj: ParsedTypings.Obj; parsingMeta: SourceMapTypings.Store; stack: { name?: string }[]; visitors: Visitor[]; input: { $originName?: string; textInput: string; textInputFlattened: string; textInputSplitByLine: string[]; }; } export type MetaArg = Omit< SourceMapTypings.Value, 'lineContent' | 'value' > & { value?: SourceMapTypings.Value['value']; }; export interface Node { addMeta: (meta: MetaArg) => void; index: number; lineContent: string; lineParts: string[]; } export type Visitor = { isSatisfied(node: Node): boolean; visit(parser: Parser, node: Node): void; }; }