Files
dm-companion/src/lib/types.ts

197 lines
3.7 KiB
TypeScript

import type { RecordModel } from "pocketbase";
export type Id<T extends string> = string & { __type: T };
export type UserId = Id<"User">;
export type CampaignId = Id<"Campaign">;
export type DocumentId = Id<"Document">;
export type ISO8601Date = string & { __type: "iso8601date" };
export type Campaign = RecordModel & {
id: CampaignId;
name: string;
owner: UserId;
};
/******************************************
* Relationships
******************************************/
export const RelationshipType = {
DiscoveredIn: "discoveredIn",
Locations: "locations",
Monsters: "monsters",
Npcs: "npcs",
Scenes: "scenes",
Secrets: "secrets",
Treasures: "treasures",
} as const;
export type RelationshipType =
(typeof RelationshipType)[keyof typeof RelationshipType];
export type Relationship = RecordModel & {
primary: DocumentId;
secondary: DocumentId[];
type: RelationshipType;
};
/******************************************
* Documents
******************************************/
export type DocumentData<K extends string, V> = {
data: Record<K, V>;
};
export type Document = RecordModel & {
id: DocumentId;
campaign: CampaignId;
data: {
[K in DocumentType]?: unknown;
};
// These two are not in Pocketbase's types, but they seem to always be present
created: ISO8601Date;
updated: ISO8601Date;
};
export type DocumentType =
| "location"
| "monster"
| "npc"
| "scene"
| "secret"
| "session"
| "treasure";
export type AnyDocument =
| Location
| Monster
| Npc
| Scene
| Secret
| Session
| Treasure;
export function getDocumentType(doc: AnyDocument): DocumentType {
if (isLocation(doc)) {
return "location";
} else if (isMonster(doc)) {
return "monster";
} else if (isNpc(doc)) {
return "npc";
} else if (isScene(doc)) {
return "scene";
} else if (isSecret(doc)) {
return "secret";
} else if (isSession(doc)) {
return "session";
} else if (isTreasure(doc)) {
return "treasure";
}
throw new Error(`Document type not found: ${JSON.stringify(doc)}`);
}
/** Locations **/
export type Location = Document &
DocumentData<
"location",
{
name: string;
description: string;
}
>;
export function isLocation(doc: Document): doc is Location {
return Object.hasOwn(doc.data, "location");
}
/** Monsters **/
export type Monster = Document &
DocumentData<
"monster",
{
name: string;
}
>;
export function isMonster(doc: Document): doc is Monster {
return Object.hasOwn(doc.data, "monster");
}
/** NPCs **/
export type Npc = Document &
DocumentData<
"npc",
{
name: string;
description: string;
}
>;
export function isNpc(doc: Document): doc is Npc {
return Object.hasOwn(doc.data, "npc");
}
/** Session **/
export type Session = Document &
DocumentData<
"session",
{
strongStart: string;
}
>;
export function isSession(doc: Document): doc is Session {
return Object.hasOwn(doc.data, "session");
}
/** Scene **/
export type Scene = Document &
DocumentData<
"scene",
{
text: string;
}
>;
export function isScene(doc: Document): doc is Scene {
return Object.hasOwn(doc.data, "scene");
}
/** Secret **/
export type Secret = Document &
DocumentData<
"secret",
{
text: string;
discovered: boolean;
}
>;
export function isSecret(doc: Document): doc is Secret {
return Object.hasOwn(doc.data, "secret");
}
/** Treasure **/
export type Treasure = Document &
DocumentData<
"treasure",
{
text: string;
discovered: boolean;
}
>;
export function isTreasure(doc: Document): doc is Treasure {
return Object.hasOwn(doc.data, "treasure");
}