import { type ArkErrors, type BaseRoot, type Morph } from "@ark/schema";
import { Callable, type conform, type ErrorMessage, type ErrorType, type isDisjoint, type Key, type numericStringKeyOf, type propValueOf, type unionToTuple } from "@ark/util";
import type { distill, Out } from "./attributes.ts";
import type { type } from "./keywords/keywords.ts";
import type { Inferred } from "./methods/base.ts";
import type { BaseCompletions } from "./parser/string.ts";
import type { InternalScope } from "./scope.ts";
type MatchParserContext = {
cases: Morph[];
$: unknown;
input: input;
checked: boolean;
key: PropertyKey | null;
};
declare namespace ctx {
type from = ctx;
type init<$, input = unknown, checked extends boolean = false> = from<{
cases: [];
$: $;
input: input;
checked: checked;
key: null;
}>;
type atKey = from<{
cases: ctx["cases"];
$: ctx["$"];
input: ctx["input"];
checked: ctx["checked"];
key: key;
}>;
}
export interface MatchParser<$> extends CaseMatchParser> {
in(def: type.validate): ChainableMatchParser, true>>;
in(...args: [typedInput] extends [never] ? [
ErrorMessage<"in requires a definition or type argument (in('string') or in())">
] : []): ChainableMatchParser>;
in(def: type.validate): ChainableMatchParser, true>>;
case: CaseParser>;
at: AtParser>;
}
type addCasesToContext = cases extends Morph[] ? ctx.from<{
$: ctx["$"];
input: ctx["input"];
cases: [...ctx["cases"], ...cases];
checked: ctx["checked"];
key: ctx["key"];
}> : never;
type addDefaultToContext> = ctx.from<{
$: ctx["$"];
input: defaultCase extends "never" ? Morph.In : ctx["input"];
cases: defaultCase extends "never" | "assert" ? ctx["cases"] : defaultCase extends Morph ? ctx["checked"] extends true ? [
(In: unknown) => ArkErrors,
...ctx["cases"],
defaultCase
] : [...ctx["cases"], defaultCase] : [
...ctx["cases"],
(In: ctx["input"]) => ArkErrors
];
checked: ctx["checked"];
key: ctx["key"];
}>;
type CaseKeyKind = "def" | "string";
type casesToMorphTuple = unionToTuple]: cases[def] extends (Morph) ? kind extends "def" ? (In: inferCaseArg) => o : (In: maybeLiftToKey) => o : never;
}>>;
type addCasesToParser = cases extends {
default: infer defaultDef extends DefaultCase;
} ? finalizeMatchParser>, defaultDef> : ChainableMatchParser>>;
type inferCaseArg = _finalizeCaseArg, ctx>, ctx, endpoint>;
type maybeLiftToKey = ctx["key"] extends PropertyKey ? {
[k in ctx["key"]]: t;
} : t;
type _finalizeCaseArg = [
distill,
distill
] extends [infer i, infer result] ? [
i
] extends [ctx["input"]] ? result : Extract extends never ? result : Extract : never;
type CaseParser = (def: type.validate, resolve: (In: inferCaseArg) => ret) => ChainableMatchParser) => ret]>>;
type validateKey = ctx["key"] extends Key ? ErrorMessage : ctx["cases"]["length"] extends 0 ? keyof ctx["input"] extends never ? key : conform : ErrorMessage;
interface StringsParser {
(def: cases extends validateStringCases ? cases : validateStringCases): addCasesToParser;
}
type validateStringCases = unknown extends ctx["input"] ? {
[k in keyof cases]?: k extends "default" ? DefaultCase : (In: _finalizeCaseArg, ctx, "out">) => unknown;
} & {
default?: DefaultCase;
} : {
[k in keyof cases]?: k extends "default" ? DefaultCase : k extends stringValue ? (In: _finalizeCaseArg, ctx, "out">) => unknown : ErrorType<`${k & string} must be a possible string value`>;
} & {
[k in stringValue]?: unknown;
} & {
default?: DefaultCase;
};
type stringValue = ctx["input"] extends string ? ctx["input"] : ctx["key"] extends keyof ctx["input"] ? ctx["input"][ctx["key"]] extends infer s extends string ? s : never : never;
interface AtParser {
(key: validateKey): ChainableMatchParser>;
>(key: validateKey, cases: cases extends validateCases ? cases : errorCases): addCasesToParser;
}
interface ChainableMatchParser {
case: CaseParser;
match: CaseMatchParser;
default: DefaultMethod;
at: AtParser;
/** @experimental */
strings: StringsParser;
}
export type DefaultCaseKeyword = "never" | "assert" | "reject";
type DefaultCase> = DefaultCaseKeyword | Morph;
type DefaultMethod = >(def: def) => finalizeMatchParser;
type validateCases = {
[def in keyof cases | BaseCompletions]?: def extends "default" ? DefaultCase : def extends number ? (In: inferCaseArg<`${def}`, ctx, "out">) => unknown : def extends type.validate ? (In: inferCaseArg) => unknown : type.validate;
};
type errorCases = {
[def in keyof cases]?: def extends "default" ? DefaultCase : def extends number ? (In: inferCaseArg<`${def}`, ctx, "out">) => unknown : def extends type.validate ? (In: inferCaseArg) => unknown : ErrorType>;
} & {
[k in BaseCompletions]?: (In: inferCaseArg) => unknown;
} & {
default?: DefaultCase;
};
export type CaseMatchParser = (def: cases extends validateCases ? cases : errorCases) => addCasesToParser;
type finalizeMatchParser> = addDefaultToContext extends (infer ctx extends MatchParserContext) ? Match : never;
export interface Match extends Inferred<(In: Morph.In) => Out>> {
(data: data): {
[i in numericStringKeyOf]: isDisjoint> extends true ? never : Morph.Out;
}[numericStringKeyOf];
}
export declare class InternalMatchParser extends Callable {
$: InternalScope;
constructor($: InternalScope);
in(def?: unknown): InternalChainedMatchParser;
at(key: Key, cases?: InternalCases): InternalChainedMatchParser | Match;
case(when: unknown, then: Morph): InternalChainedMatchParser;
}
type InternalCases = Record;
type InternalCaseParserFn = (cases: InternalCases) => InternalChainedMatchParser | Match;
type CaseEntry = [BaseRoot, Morph] | ["default", DefaultCase];
export declare class InternalChainedMatchParser extends Callable {
$: InternalScope;
in: BaseRoot | undefined;
protected key: Key | undefined;
protected branches: BaseRoot[];
constructor($: InternalScope, In?: BaseRoot);
at(key: Key, cases?: InternalCases): InternalChainedMatchParser | Match;
case(def: unknown, resolver: Morph): InternalChainedMatchParser;
protected caseEntry(node: BaseRoot, resolver: Morph): InternalChainedMatchParser;
match(cases: InternalCases): InternalChainedMatchParser | Match;
strings(cases: InternalCases): InternalChainedMatchParser | Match;
protected caseEntries(entries: CaseEntry[]): InternalChainedMatchParser | Match;
default(defaultCase: DefaultCase): Match;
}
export declare const throwOnDefault: ArkErrors.Handler;
export declare const chainedAtMessage = "A key matcher must be specified before the first case i.e. match.at('foo') or match.in