diff --git a/pb_migrations/1751082417_updated_documents.js b/pb_migrations/1751082417_updated_documents.js
new file mode 100644
index 0000000..037b083
--- /dev/null
+++ b/pb_migrations/1751082417_updated_documents.js
@@ -0,0 +1,46 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_3332084752")
+
+ // update collection data
+ unmarshal({
+ "indexes": [
+ "CREATE INDEX `idx_gxNj5R3hxv` ON `documents` (`type`)"
+ ]
+ }, collection)
+
+ // add field
+ collection.fields.addAt(3, new Field({
+ "hidden": false,
+ "id": "select2363381545",
+ "maxSelect": 1,
+ "name": "type",
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "select",
+ "values": [
+ "location",
+ "monster",
+ "npc",
+ "scene",
+ "secret",
+ "session",
+ "treasure"
+ ]
+ }))
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_3332084752")
+
+ // update collection data
+ unmarshal({
+ "indexes": []
+ }, collection)
+
+ // remove field
+ collection.fields.removeById("select2363381545")
+
+ return app.save(collection)
+})
diff --git a/pb_migrations/1751082429_updated_documents.js b/pb_migrations/1751082429_updated_documents.js
new file mode 100644
index 0000000..1d05922
--- /dev/null
+++ b/pb_migrations/1751082429_updated_documents.js
@@ -0,0 +1,25 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_3332084752")
+
+ // update collection data
+ unmarshal({
+ "indexes": [
+ "CREATE INDEX `idx_gxNj5R3hxv` ON `documents` (`type`)",
+ "CREATE INDEX `idx_KtpMErDe1C` ON `documents` (`campaign`)"
+ ]
+ }, collection)
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_3332084752")
+
+ // update collection data
+ unmarshal({
+ "indexes": [
+ "CREATE INDEX `idx_gxNj5R3hxv` ON `documents` (`type`)"
+ ]
+ }, collection)
+
+ return app.save(collection)
+})
diff --git a/pb_migrations/1751082553_extract_document_types.js b/pb_migrations/1751082553_extract_document_types.js
new file mode 100644
index 0000000..d4dd101
--- /dev/null
+++ b/pb_migrations/1751082553_extract_document_types.js
@@ -0,0 +1,55 @@
+const DocType = [
+ "location",
+ "monster",
+ "npc",
+ "scene",
+ "secret",
+ "session",
+ "treasure",
+];
+
+function parseJsonB(data) {
+ if (typeof data === "string") {
+ return JSON.parse(data);
+ } else if (data instanceof Array) {
+ return JSON.parse(String.fromCharCode.apply(String, data));
+ }
+ throw new Error("Unsupported data type for JSON parsing");
+}
+
+///
+migrate(
+ (app) => {
+ let documents = app.findAllRecords("documents");
+ console.log("Records to parse: ", documents.length);
+
+ documents: for (const doc of documents) {
+ if (!doc) continue;
+
+ let data = parseJsonB(doc.get("data"));
+
+ if (data[""]) {
+ data = data[""];
+ }
+ for (const t of DocType) {
+ if (data[t]) {
+ doc.set("type", t);
+ doc.set("data", data[t]);
+ app.save(doc);
+ continue documents;
+ }
+ }
+ throw new Error(`Unrecognized data: ${JSON.stringify(data)}`);
+ }
+ },
+ (app) => {
+ // add down queries...
+ let documents = app.findAllRecords("documents");
+
+ for (const doc of documents) {
+ if (!doc) continue;
+ doc.set("data", { [doc.get("type")]: doc.get("data") });
+ app.save(doc);
+ }
+ },
+);
diff --git a/src/components/documents/DocumentEditForm.tsx b/src/components/documents/DocumentEditForm.tsx
index 6cf3f05..e19d9d5 100644
--- a/src/components/documents/DocumentEditForm.tsx
+++ b/src/components/documents/DocumentEditForm.tsx
@@ -1,13 +1,4 @@
-import {
- isLocation,
- isMonster,
- isNpc,
- isScene,
- isSecret,
- isSession,
- isTreasure,
- type AnyDocument,
-} from "@/lib/types";
+import { type AnyDocument } from "@/lib/types";
import { LocationEditForm } from "./location/LocationEditForm";
import { MonsterEditForm } from "./monsters/MonsterEditForm";
import { NpcEditForm } from "./npc/NpcEditForm";
@@ -16,41 +7,24 @@ import { SecretEditForm } from "./secret/SecretEditForm";
import { SessionEditForm } from "./session/SessionEditForm";
import { TreasureEditForm } from "./treasure/TreasureEditForm";
-function assertUnreachable(_x: never): never {
- throw new Error("DocumentForm switch is not exhaustive");
-}
-
/**
* Renders a form for any document type depending on the relationship.
*/
export const DocumentEditForm = ({ document }: { document: AnyDocument }) => {
- if (isLocation(document)) {
- return ;
+ switch (document.type) {
+ case "location":
+ return ;
+ case "monster":
+ return ;
+ case "npc":
+ return ;
+ case "scene":
+ return ;
+ case "secret":
+ return ;
+ case "session":
+ return ;
+ case "treasure":
+ return ;
}
-
- if (isMonster(document)) {
- return ;
- }
-
- if (isNpc(document)) {
- return ;
- }
-
- if (isScene(document)) {
- return ;
- }
-
- if (isSecret(document)) {
- return ;
- }
-
- if (isSession(document)) {
- return ;
- }
-
- if (isTreasure(document)) {
- return ;
- }
-
- return assertUnreachable(document);
};
diff --git a/src/components/documents/DocumentPrintRow.tsx b/src/components/documents/DocumentPrintRow.tsx
index 123fbb5..835edb3 100644
--- a/src/components/documents/DocumentPrintRow.tsx
+++ b/src/components/documents/DocumentPrintRow.tsx
@@ -1,64 +1,33 @@
// DocumentRow.tsx
// Generic row component for displaying any document type.
-import {
- isLocation,
- isMonster,
- isNpc,
- isScene,
- isSecret,
- isSession,
- isTreasure,
- type Document,
-} from "@/lib/types";
+import { type AnyDocument } from "@/lib/types";
import { LocationPrintRow } from "./location/LocationPrintRow";
import { MonsterPrintRow } from "./monsters/MonsterPrintRow";
-import { TreasurePrintRow } from "./treasure/TreasurePrintRow";
-import { SecretPrintRow } from "./secret/SecretPrintRow";
import { NpcPrintRow } from "./npc/NpcPrintRow";
import { ScenePrintRow } from "./scene/ScenePrintRow";
+import { SecretPrintRow } from "./secret/SecretPrintRow";
import { SessionPrintRow } from "./session/SessionPrintRow";
+import { TreasurePrintRow } from "./treasure/TreasurePrintRow";
/**
* Renders a row for any document type. Prioritizes Session, then Secret, then falls back to ID and creation time.
* If rendering a SecretRow, uses the provided session prop if available.
*/
-export const DocumentPrintRow = ({ document }: { document: Document }) => {
- if (isLocation(document)) {
- return ;
+export const DocumentPrintRow = ({ document }: { document: AnyDocument }) => {
+ switch (document.type) {
+ case "location":
+ return ;
+ case "monster":
+ return ;
+ case "npc":
+ return ;
+ case "scene":
+ return ;
+ case "secret":
+ return ;
+ case "session":
+ return ;
+ case "treasure":
+ return ;
}
-
- if (isMonster(document)) {
- return ;
- }
-
- if (isNpc(document)) {
- return ;
- }
-
- if (isSession(document)) {
- return ;
- }
-
- if (isSecret(document)) {
- return ;
- }
-
- if (isScene(document)) {
- return ;
- }
-
- if (isTreasure(document)) {
- return ;
- }
-
- // Fallback: show ID and creation time
- return (
-
-
- Unrecognized Document
-
-
ID: {document.id}
-
Created: {document.created}
-
- );
};
diff --git a/src/components/documents/DocumentRow.tsx b/src/components/documents/DocumentRow.tsx
index 9919171..e7cde0e 100644
--- a/src/components/documents/DocumentRow.tsx
+++ b/src/components/documents/DocumentRow.tsx
@@ -1,17 +1,7 @@
// DocumentRow.tsx
// Generic row component for displaying any document type.
import { SecretToggleRow } from "@/components/documents/secret/SecretToggleRow";
-import {
- isLocation,
- isMonster,
- isNpc,
- isScene,
- isSecret,
- isSession,
- isTreasure,
- type Document,
- type Session,
-} from "@/lib/types";
+import { type AnyDocument, type Session } from "@/lib/types";
import { BasicRow } from "./BasicRow";
import { TreasureToggleRow } from "./treasure/TreasureToggleRow";
@@ -23,63 +13,47 @@ export const DocumentRow = ({
document,
session,
}: {
- document: Document;
+ document: AnyDocument;
session?: Session;
}) => {
- if (isLocation(document)) {
- return (
-
- );
- }
+ switch (document.type) {
+ case "location":
+ return (
+
+ );
- if (isMonster(document)) {
- return ;
- }
+ case "monster":
+ return ;
- if (isNpc(document)) {
- return (
-
- );
- }
+ case "npc":
+ return (
+
+ );
- if (isSession(document)) {
- return (
-
- );
- }
+ case "session":
+ return (
+
+ );
- if (isSecret(document)) {
- return ;
- }
+ case "secret":
+ return ;
- if (isScene(document)) {
- return ;
- }
+ case "scene":
+ return ;
- if (isTreasure(document)) {
- return ;
+ case "treasure":
+ return ;
}
-
- // Fallback: show ID and creation time
- return (
-
-
- Unrecognized Document
-
-
ID: {document.id}
-
Created: {document.created}
-
- );
};
diff --git a/src/components/documents/location/LocationEditForm.tsx b/src/components/documents/location/LocationEditForm.tsx
index 19854ef..17f283f 100644
--- a/src/components/documents/location/LocationEditForm.tsx
+++ b/src/components/documents/location/LocationEditForm.tsx
@@ -10,10 +10,7 @@ export const LocationEditForm = ({ location }: { location: Location }) => {
await pb.collection("documents").update(location.id, {
data: {
...location.data,
- location: {
- ...location.data.location,
- name,
- },
+ name,
},
});
}
@@ -22,10 +19,7 @@ export const LocationEditForm = ({ location }: { location: Location }) => {
await pb.collection("documents").update(location.id, {
data: {
...location.data,
- location: {
- ...location.data.location,
- description,
- },
+ description,
},
});
}
@@ -34,11 +28,11 @@ export const LocationEditForm = ({ location }: { location: Location }) => {
diff --git a/src/components/documents/location/LocationPrintRow.tsx b/src/components/documents/location/LocationPrintRow.tsx
index 00c1694..e59f8df 100644
--- a/src/components/documents/location/LocationPrintRow.tsx
+++ b/src/components/documents/location/LocationPrintRow.tsx
@@ -6,8 +6,8 @@ import type { Location } from "@/lib/types";
export const LocationPrintRow = ({ location }: { location: Location }) => {
return (
- {location.data.location.name}
- {location.data.location.description}
+ {location.data.name}
+ {location.data.description}
);
};
diff --git a/src/components/documents/location/NewLocationForm.tsx b/src/components/documents/location/NewLocationForm.tsx
index 641ec37..a9021df 100644
--- a/src/components/documents/location/NewLocationForm.tsx
+++ b/src/components/documents/location/NewLocationForm.tsx
@@ -25,11 +25,10 @@ export const NewLocationForm = ({
try {
const locationDoc: Location = await pb.collection("documents").create({
campaign,
+ type: "location",
data: {
- location: {
- name,
- description,
- },
+ name,
+ description,
},
});
setName("");
diff --git a/src/components/documents/monsters/MonsterEditForm.tsx b/src/components/documents/monsters/MonsterEditForm.tsx
index 2b57ee3..258e352 100644
--- a/src/components/documents/monsters/MonsterEditForm.tsx
+++ b/src/components/documents/monsters/MonsterEditForm.tsx
@@ -10,10 +10,7 @@ export const MonsterEditForm = ({ monster }: { monster: Monster }) => {
await pb.collection("documents").update(monster.id, {
data: {
...monster.data,
- monster: {
- ...monster.data.monster,
- name,
- },
+ name,
},
});
}
@@ -22,7 +19,7 @@ export const MonsterEditForm = ({ monster }: { monster: Monster }) => {
diff --git a/src/components/documents/monsters/MonsterPrintRow.tsx b/src/components/documents/monsters/MonsterPrintRow.tsx
index 0b4fd30..2c16897 100644
--- a/src/components/documents/monsters/MonsterPrintRow.tsx
+++ b/src/components/documents/monsters/MonsterPrintRow.tsx
@@ -4,5 +4,5 @@ import type { Monster } from "@/lib/types";
* Renders an editable monster row
*/
export const MonsterPrintRow = ({ monster }: { monster: Monster }) => {
- return {monster.data.monster.name};
+ return {monster.data..name};
};
diff --git a/src/components/documents/monsters/NewMonsterForm.tsx b/src/components/documents/monsters/NewMonsterForm.tsx
index 66e83d1..893f382 100644
--- a/src/components/documents/monsters/NewMonsterForm.tsx
+++ b/src/components/documents/monsters/NewMonsterForm.tsx
@@ -25,11 +25,10 @@ export const NewMonsterForm = ({
try {
const monsterDoc: Monster = await pb.collection("documents").create({
campaign,
+ type: "monster",
data: {
- monster: {
- name,
- description,
- },
+ name,
+ description,
},
});
setName("");
diff --git a/src/components/documents/npc/NewNpcForm.tsx b/src/components/documents/npc/NewNpcForm.tsx
index f70b59c..9c964a0 100644
--- a/src/components/documents/npc/NewNpcForm.tsx
+++ b/src/components/documents/npc/NewNpcForm.tsx
@@ -25,11 +25,10 @@ export const NewNpcForm = ({
try {
const npcDoc: Npc = await pb.collection("documents").create({
campaign,
+ type: "npc",
data: {
- npc: {
- name,
- description,
- },
+ name,
+ description,
},
});
setName("");
diff --git a/src/components/documents/npc/NpcEditForm.tsx b/src/components/documents/npc/NpcEditForm.tsx
index 0e9f18a..0a4ad36 100644
--- a/src/components/documents/npc/NpcEditForm.tsx
+++ b/src/components/documents/npc/NpcEditForm.tsx
@@ -10,10 +10,7 @@ export const NpcEditForm = ({ npc }: { npc: Npc }) => {
await pb.collection("documents").update(npc.id, {
data: {
...npc.data,
- npc: {
- ...npc.data.npc,
- name,
- },
+ name,
},
});
}
@@ -22,10 +19,7 @@ export const NpcEditForm = ({ npc }: { npc: Npc }) => {
await pb.collection("documents").update(npc.id, {
data: {
...npc.data,
- npc: {
- ...npc.data.npc,
- description,
- },
+ description,
},
});
}
@@ -34,11 +28,11 @@ export const NpcEditForm = ({ npc }: { npc: Npc }) => {
diff --git a/src/components/documents/npc/NpcPrintRow.tsx b/src/components/documents/npc/NpcPrintRow.tsx
index de9366c..eda5f05 100644
--- a/src/components/documents/npc/NpcPrintRow.tsx
+++ b/src/components/documents/npc/NpcPrintRow.tsx
@@ -6,8 +6,8 @@ import type { Npc } from "@/lib/types";
export const NpcPrintRow = ({ npc }: { npc: Npc }) => {
return (
- {npc.data.npc.name}
- {npc.data.npc.description}
+ {npc.data.name}
+ {npc.data.description}
);
};
diff --git a/src/components/documents/scene/NewSceneForm.tsx b/src/components/documents/scene/NewSceneForm.tsx
index b3c4aa6..17e1ff7 100644
--- a/src/components/documents/scene/NewSceneForm.tsx
+++ b/src/components/documents/scene/NewSceneForm.tsx
@@ -26,10 +26,9 @@ export const NewSceneForm = ({
try {
const sceneDoc: Scene = await pb.collection("documents").create({
campaign,
+ type: "scene",
data: {
- scene: {
- text,
- },
+ text,
},
});
setText("");
diff --git a/src/components/documents/scene/SceneEditForm.tsx b/src/components/documents/scene/SceneEditForm.tsx
index 407c11e..7a9db30 100644
--- a/src/components/documents/scene/SceneEditForm.tsx
+++ b/src/components/documents/scene/SceneEditForm.tsx
@@ -13,9 +13,7 @@ export const SceneEditForm = ({ scene }: { scene: Scene }) => {
await pb.collection("documents").update(scene.id, {
data: {
...scene.data,
- scene: {
- text,
- },
+ text,
},
});
queryClient.invalidateQueries({
@@ -25,7 +23,7 @@ export const SceneEditForm = ({ scene }: { scene: Scene }) => {
return (
);
};
diff --git a/src/components/documents/scene/ScenePrintRow.tsx b/src/components/documents/scene/ScenePrintRow.tsx
index de5b162..697b4bf 100644
--- a/src/components/documents/scene/ScenePrintRow.tsx
+++ b/src/components/documents/scene/ScenePrintRow.tsx
@@ -4,5 +4,5 @@ import type { Scene } from "@/lib/types";
* Renders an editable scene row
*/
export const ScenePrintRow = ({ scene }: { scene: Scene }) => {
- return {scene.data.scene.text};
+ return {scene.data.text};
};
diff --git a/src/components/documents/secret/NewSecretForm.tsx b/src/components/documents/secret/NewSecretForm.tsx
index f0c9865..fe6c63f 100644
--- a/src/components/documents/secret/NewSecretForm.tsx
+++ b/src/components/documents/secret/NewSecretForm.tsx
@@ -26,11 +26,10 @@ export const NewSecretForm = ({
try {
const secretDoc: Secret = await pb.collection("documents").create({
campaign,
+ type: "secret",
data: {
- secret: {
- text: newSecret,
- discovered: false,
- },
+ text: newSecret,
+ discovered: false,
},
});
setNewSecret("");
diff --git a/src/components/documents/secret/SecretEditForm.tsx b/src/components/documents/secret/SecretEditForm.tsx
index d099482..6cf837b 100644
--- a/src/components/documents/secret/SecretEditForm.tsx
+++ b/src/components/documents/secret/SecretEditForm.tsx
@@ -28,10 +28,7 @@ export const SecretEditForm = ({
await pb.collection("documents").update(secret.id, {
data: {
...secret.data,
- secret: {
- ...(secret.data as any).secret,
- discovered: newChecked,
- },
+ discovered: newChecked,
},
});
if (session || !newChecked) {
@@ -62,10 +59,7 @@ export const SecretEditForm = ({
await pb.collection("documents").update(secret.id, {
data: {
...secret.data,
- secret: {
- ...secret.data.secret,
- text,
- },
+ text,
},
});
}
@@ -82,7 +76,7 @@ export const SecretEditForm = ({
/>
diff --git a/src/components/documents/secret/SecretToggleRow.tsx b/src/components/documents/secret/SecretToggleRow.tsx
index bd1b7f0..ca23fd4 100644
--- a/src/components/documents/secret/SecretToggleRow.tsx
+++ b/src/components/documents/secret/SecretToggleRow.tsx
@@ -68,11 +68,7 @@ export const SecretToggleRow = ({
aria-label="Discovered"
disabled={loading}
/>
-
- {(secret.data as any)?.secret?.text || (
- (No secret text)
- )}
-
+ {secret.data.text}
);
};
diff --git a/src/components/documents/session/SessionEditForm.tsx b/src/components/documents/session/SessionEditForm.tsx
index 7af3776..25bca14 100644
--- a/src/components/documents/session/SessionEditForm.tsx
+++ b/src/components/documents/session/SessionEditForm.tsx
@@ -7,10 +7,7 @@ export const SessionEditForm = ({ session }: { session: Session }) => {
await pb.collection("documents").update(session.id, {
data: {
...session.data,
- session: {
- ...session.data.session,
- strongStart,
- },
+ strongStart,
},
});
}
@@ -19,7 +16,7 @@ export const SessionEditForm = ({ session }: { session: Session }) => {