-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
more helpful errors when tracks/clocks/characters/etc are unable to r…
…ender Fixes #81
- Loading branch information
Showing
18 changed files
with
386 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,131 +1,76 @@ | ||
import { type CachedMetadata } from "obsidian"; | ||
import { updaterWithContext } from "utils/update"; | ||
import { z } from "zod"; | ||
import { | ||
CharacterLens, | ||
CharacterValidater, | ||
ValidatedCharacter, | ||
characterLens, | ||
} from "./characters/lens"; | ||
import { Datastore } from "./datastore"; | ||
import { BaseIndexer } from "./indexer/indexer"; | ||
import { Either, Left, Right } from "./utils/either"; | ||
|
||
export class CharacterTracker implements ReadonlyMap<string, CharacterResult> { | ||
constructor( | ||
public readonly index: Map<string, CharacterResult> = new Map(), | ||
) {} | ||
|
||
forEach( | ||
callbackfn: ( | ||
value: CharacterResult, | ||
key: string, | ||
map: ReadonlyMap<string, CharacterResult>, | ||
) => void, | ||
thisArg?: unknown, | ||
): void { | ||
this.index.forEach(callbackfn, thisArg); | ||
} | ||
get(key: string): CharacterResult | undefined { | ||
return this.index.get(key); | ||
} | ||
has(key: string): boolean { | ||
return this.index.has(key); | ||
} | ||
get size(): number { | ||
return this.index.size; | ||
} | ||
entries(): IterableIterator<[string, CharacterResult]> { | ||
return this.index.entries(); | ||
} | ||
keys(): IterableIterator<string> { | ||
return this.index.keys(); | ||
} | ||
values(): IterableIterator<CharacterResult> { | ||
return this.index.values(); | ||
} | ||
[Symbol.iterator](): IterableIterator<[string, CharacterResult]> { | ||
return this.index[Symbol.iterator](); | ||
} | ||
|
||
*validCharacterEntries(): Generator<[string, CharacterContext]> { | ||
for (const [key, val] of this.entries()) { | ||
if (val.isRight()) { | ||
yield [key, val.value]; | ||
} | ||
} | ||
} | ||
|
||
activeCharacter(): [string, CharacterContext] { | ||
if (this.size == 0) { | ||
throw new MissingCharacterError("no valid characters found"); | ||
} else if (this.size > 1) { | ||
throw new MissingCharacterError( | ||
"we don't yet support multiple characters", | ||
); | ||
} | ||
|
||
const [[key, val]] = this.entries(); | ||
if (val.isLeft()) { | ||
throw val.error; | ||
} | ||
|
||
return [key, val.value]; | ||
} | ||
} | ||
import { BaseIndexer, IndexOf, IndexUpdate } from "./indexer/indexer"; | ||
|
||
export class CharacterError extends Error {} | ||
|
||
export class MissingCharacterError extends Error {} | ||
|
||
export class InvalidCharacterError extends Error {} | ||
|
||
export class CharacterIndexer extends BaseIndexer<CharacterResult> { | ||
export class CharacterIndexer extends BaseIndexer< | ||
CharacterContext, | ||
z.ZodError | ||
> { | ||
readonly id: string = "character"; | ||
|
||
constructor( | ||
tracker: CharacterTracker, | ||
protected readonly dataStore: Datastore, | ||
) { | ||
super(tracker.index); | ||
constructor(protected readonly dataStore: Datastore) { | ||
super(); | ||
} | ||
|
||
processFile( | ||
path: string, | ||
cache: CachedMetadata, | ||
): CharacterResult | undefined { | ||
): IndexUpdate<CharacterContext, z.ZodError> { | ||
if (cache.frontmatter == null) { | ||
throw new Error("missing frontmatter cache"); | ||
} | ||
const { validater, lens } = characterLens(this.dataStore.ruleset); | ||
try { | ||
const result = validater(cache.frontmatter); | ||
return Right.create(new CharacterContext(result, lens, validater)); | ||
} catch (e) { | ||
return Left.create( | ||
e instanceof Error ? e : new Error("unexpected error", { cause: e }), | ||
); | ||
} | ||
return validater(cache.frontmatter).map( | ||
(character) => new CharacterContext(character, lens, validater), | ||
); | ||
} | ||
} | ||
|
||
// TODO: this type is really weird. should a validatedcharacter carry around all of the context | ||
// used to produce it here? Or should that be coming from the datastore as needed? | ||
export type CharacterResult<E extends Error = Error> = Either< | ||
E, | ||
CharacterContext | ||
>; | ||
|
||
export class CharacterContext { | ||
constructor( | ||
public readonly character: ValidatedCharacter, | ||
public readonly lens: CharacterLens, | ||
public readonly validater: (data: unknown) => ValidatedCharacter, | ||
public readonly validater: CharacterValidater, | ||
) {} | ||
|
||
get updater() { | ||
return updaterWithContext<ValidatedCharacter, CharacterContext>( | ||
(data) => this.validater(data), | ||
(data) => this.validater(data).unwrap(), | ||
(character) => character.raw, | ||
this, | ||
); | ||
} | ||
} | ||
|
||
export type CharacterTracker = IndexOf<CharacterIndexer>; | ||
|
||
export function activeCharacter( | ||
characters: CharacterTracker, | ||
): [string, CharacterContext] { | ||
if (characters.size == 0) { | ||
throw new MissingCharacterError("no valid characters found"); | ||
} else if (characters.size > 1) { | ||
throw new MissingCharacterError("we don't yet support multiple characters"); | ||
} | ||
|
||
const [[key, val]] = characters.entries(); | ||
if (val.isLeft()) { | ||
throw val.error; | ||
} | ||
|
||
return [key, val.value]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.