Skip to content

Commit

Permalink
Merge pull request #417 from scottbenton/fix/homebrew-fixes
Browse files Browse the repository at this point in the history
Fix/homebrew fixes
  • Loading branch information
scottbenton authored May 4, 2024
2 parents 0cb6b0c + 6c1c0b0 commit ccd7736
Show file tree
Hide file tree
Showing 343 changed files with 3,158 additions and 3,958 deletions.
15 changes: 0 additions & 15 deletions functions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2,728 changes: 812 additions & 1,916 deletions package-lock.json

Large diffs are not rendered by default.

107 changes: 107 additions & 0 deletions src/api-calls/DatabaseStructure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Database Structure

```
// Note meaning
H - Hardcoded document name (not auto-id'd)
D - Deprecated or soon to be deprecated
├── characters <characterId, CharacterDocument>
├── assets <assetId, AssetDocument>
├── game-log <logId, GameLogDocument> // Gets converted to Roll
├── notes <noteId, NoteDocument>
├── content (H) <"content", NoteContentDocument>
├── settings (HD) <"settings", SettingsDocument>
├── tracks <trackId, TrackDocument> // Gets converted to Track
├── campaigns <campaignId, CampaignDocument>
├── assets <assetId, AssetDocument>
├── game-log <logId, GameLogDocument> // Gets converted to Roll
├── notes <noteId, NoteDocument>
├── content (H) <"content", NoteContentDocument>
├── settings (HD) <"settings", SettingsDocument>
├── tracks <trackId, TrackDocument> // Gets converted to Track
├── worlds <worldId, WorldDocument> // Gets converted to World
├── locations <locationId, LocationDocument> // Ironsworn only, gets converted to Location
├── public (H) <"notes", LocationNotesDocument>
├── private (H) <"details", GMLocationDocument>
├── lore <loreId, LoreDocument> // Gets converted to Lore
├── public (H) <"notes", LoreNotesDocument>
├── private (H) <"details", GMLoreDocument>
├── npcs <npcId, NPCDocument> // Gets converted to NPC
├── public (H) <"notes", NPCNotesDocument>
├── private (H) <"details", GMNPCDocument> // Gets converted to GMNPC
├── sectors <sectorId, SectorDocument> // Gets converted to Sector
├── public (H) <"notes", NoteContentDocument>
├── private (H) <"notes", NoteContentDocument>
├── locations <sectorLocationId, SectorLocationDocument>
├── homebrew
├── collections (H) <"collections", <collectionId, HomebrewCollectionDocument>> // High level - container for everything else
├── asset_collections (H) <"asset_collections", <assetCollectionId, HomebrewAssetCollectionDocument>>
├── assets (H) <"assets", <assetId, HomebrewAssetDocument>>
├── condition_meters (H) <"condition_meters", <conditionMeterId, HomebrewConditionMeterDocument>>
├── !! editorInviteKeys // Dealt with on the backend
├── impacts (H) <"impacts", <impactCategoryId, HomebrewImpactCategoryDocument>>
├── legacy_tracks <"legacy_tracks", <legacyTrackId, HomebrewLegacyTrackDocument>>
├── move_categories <"move_categories", <moveCategoryId, HomebrewMoveCategoryDocument>>
├── moves <"moves", <moveId, HomebrewMoveDocument>>
├── non_linear_meters <"non_linear_meters", <nonLinearMeterId, HomebrewNonLinearMeterDocument>>
├── oracle_collections <"oracle_collections", <oracleCollectionId, HomebrewOracleCollectionDocument>>
├── oracle_tables <"oracle_tables", <oracleTableId, HomebrewOracleTableDocument>>
├── stats <"stats", <statId, HomebrewStatDocument>>
├── users <userId, UserDocument>
├── custom-moves (HD) <"custom-moves", CustomMoveDocument>>
├── custom-oracles (HD) <"custom-oracles", CustomOracleDocument>>
├── settings (H) <"accessibility", AccessibilitySettingsDocument> | <"oracle" | OracleSettingsDocument>
```

## Type Links

| Type | File |
| -------------------------------- | -------------------------------------------------------------------------------------------------------- |
| **Characters and Campaigns** | |
| CharacterDocument | [\_character.type](./character/_character.type.ts) |
| CampaignDocument | [\_campaign.type](./campaign/_campaign.type.ts) |
| TrackDocument | [\_track.type](./tracks/_track.type.ts) |
| AssetDocument | [\_asset.type](./assets/_asset.type.ts) |
| GameLogDocument | [\_game-log.type](./game-log/_game-log.type.ts) |
| NoteDocument | [\_notes.type](./notes/_notes.type.ts) |
| NoteContentDocument | [\_notes.type](./notes/_notes.type.ts) |
| SettingsDocument | [\_character-campaign-settings.type](./character-campaign-settings/_character-campaign-settings.type.ts) |
| **Worlds** | |
| WorldDocument | [\_world.type](./world/_world.type.ts) |
| LocationDocument (and related) | [\_location.type](./world/locations/_locations.type.ts) |
| LoreDocument (and related) | [\_lore.type](./world/lore/_lore.type.ts) |
| NPCDocument (and related) | [\_npcs.type](./world/npcs/_npcs.type.ts) |
| SectorDocument (and related) | [\_sectors.type](./world/sectors/_sectors.type.ts) |
| SectorLocationDocument | [\_sectorLocations.type](./world/sectors/sectorLocations/_sectorLocations.type.ts) |
| **Homebrew Beta** | |
| HomebrewCollectionDocument | [\_homebrewCollection.type](./homebrew/_homebrewCollection.type.ts) |
| HomebrewAssetCollectionDocument | [\_homebrewAssetCollection.type](./homebrew/assets/collections/_homebrewAssetCollection.type) |
| HomebrewAssetDocument | [\_homebrewAssets.type](./homebrew/assets/assets/_homebrewAssets.type.ts) |
| HomebrewConditionMeterDocument | [\_homebrewConditionMeters.type](./homebrew/rules/conditionMeters/_homebrewConditionMeters.type.ts) |
| HomebrewImpactCategoryDocument | [\_homebrewImpacts.type](./homebrew/rules/impacts/_homebrewImpacts.type.ts) |
| HomebrewLegacyTrackDocument | [\_homebrewLegacyTrack.type](./homebrew/rules/legacyTracks/_homebrewLegacyTrack.type.ts) |
| HomebrewMoveCategoryDocument | [\_homebrewMoveCategory.type](./homebrew/moves/categories/_homebrewMoveCategory.type.ts) |
| HomebrewMoveDocument | [\_homebrewMove.type](./homebrew/moves/moves/_homebrewMove.type.ts) |
| HomebrewNonLinearMeterDocument | [\_homebrewNonLinearMeter.type](./homebrew/rules/nonLinearMeters/_homebrewNonLinearMeter.type.ts) |
| HomebrewOracleCollectionDocument | [\_homebrewOracleCollection.type](./homebrew/oracles/collections/_homebrewOracleCollection.type.ts) |
| HomebrewOracleTableDocument | [\_homebrewOracleTable.type](./homebrew/oracles/tables/_homebrewOracleTable.type.ts) |
| HomebrewStatDocument | [\_homebrewStat.type](./homebrew/rules/stats/_homebrewStat.type.ts) |
| **Users** | |
| UserDocument | [\_user.type](./user/_user.type.ts) |
| CustomMoveDocument | [\_custom-moves.type](./user/custom-moves/_custom-moves.type.ts) |
| CustomOracleDocument | [\_custom-oracles.type](./user/custom-oracles/_custom-oracles.type.ts) |
| AccessibilitySettingsDocument | [\_settings.type](./user/settings/_settings.type.ts) |
| OracleSettingsDocument | [\_settings.type](./user/settings/_settings.type.ts) |

---

# Related Notes

## Converting Bytes to another format

Rich text across the app (not including homebrew) is stored as `Bytes` in the database, and then converted to uint8Arrays.
The reason for doing this instead of using a more common form (like markdown), is so that I can take advantage of the realtime collaboration features from [YDocs](https://yjs.dev/) and [TipTap](https://tiptap.dev/docs/editor/guide/output#introduction).
If you are looking to export one of these fields (Hi Kat!), you can convert this either to JSON (in a structure very specific to Prosemirror Rich Text) or to HTML.

In order to do this, you will need to read it into a TipTap editor (using the same extensions as the original), and then call the [export function](https://tiptap.dev/docs/editor/guide/output#introduction) of your choice.
I've done this once before, so feel free to reach out if you need a hand!
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import type { Asset as DataforgedAsset } from "dataforged";

export interface StoredAsset {
export interface AssetDocument {
id: string;
enabledAbilities: Record<number, boolean>;
optionValues?: Record<string, string>;
controlValues?: Record<string, boolean | string | number>;
order: number;

// Deprecated - the above fields should be used instead
// !! note - the database may not have the upper fields filled yet, I have not ran (or written) the migration script yet
// TODO - Remove when assets are updated
customAsset?: DataforgedAsset | null;
conditions?: Record<string, boolean>;
Expand Down
10 changes: 5 additions & 5 deletions src/api-calls/assets/_getRef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
doc,
DocumentReference,
} from "firebase/firestore";
import { StoredAsset } from "types/Asset.type";
import { AssetDocument } from "api-calls/assets/_asset.type";

export function constructCharacterAssetCollectionPath(characterId: string) {
return `/characters/${characterId}/assets`;
Expand Down Expand Up @@ -33,26 +33,26 @@ export function getCharacterAssetCollection(characterId: string) {
return collection(
firestore,
constructCharacterAssetCollectionPath(characterId)
) as CollectionReference<StoredAsset>;
) as CollectionReference<AssetDocument>;
}

export function getCharacterAssetDoc(characterId: string, assetId: string) {
return doc(
firestore,
constructCharacterAssetDocPath(characterId, assetId)
) as DocumentReference<StoredAsset>;
) as DocumentReference<AssetDocument>;
}

export function getCampaignAssetCollection(campaignId: string) {
return collection(
firestore,
constructCampaignAssetCollectionPath(campaignId)
) as CollectionReference<StoredAsset>;
) as CollectionReference<AssetDocument>;
}

export function getCampaignAssetDoc(campaignId: string, assetId: string) {
return doc(
firestore,
constructCampaignAssetDocPath(campaignId, assetId)
) as DocumentReference<StoredAsset>;
) as DocumentReference<AssetDocument>;
}
4 changes: 2 additions & 2 deletions src/api-calls/assets/addAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import {
getCampaignAssetCollection,
getCharacterAssetCollection,
} from "./_getRef";
import { StoredAsset } from "types/Asset.type";
import { AssetDocument } from "api-calls/assets/_asset.type";
import { createApiFunction } from "api-calls/createApiFunction";

interface AddAssetParams {
campaignId?: string;
characterId?: string;
asset: StoredAsset;
asset: AssetDocument;
}

export const addAsset = createApiFunction<AddAssetParams, void>((params) => {
Expand Down
6 changes: 3 additions & 3 deletions src/api-calls/assets/listenToAssets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import {
getCampaignAssetCollection,
getCharacterAssetCollection,
} from "./_getRef";
import { StoredAsset } from "types/Asset.type";
import { AssetDocument } from "api-calls/assets/_asset.type";

export function listenToAssets(
characterId: string | undefined,
campaignId: string | undefined,
onAssets: (assets: { [assetId: string]: StoredAsset }) => void,
onAssets: (assets: { [assetId: string]: AssetDocument }) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onError: (error: any) => void
) {
Expand All @@ -21,7 +21,7 @@ export function listenToAssets(
? getCharacterAssetCollection(characterId)
: getCampaignAssetCollection(campaignId as string),
(snapshot) => {
const assetMap: { [assetId: string]: StoredAsset } = {};
const assetMap: { [assetId: string]: AssetDocument } = {};

snapshot.docs.forEach((doc) => (assetMap[doc.id] = doc.data()));
onAssets(assetMap);
Expand Down
4 changes: 2 additions & 2 deletions src/api-calls/assets/updateAsset.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { PartialWithFieldValue, updateDoc } from "firebase/firestore";
import { getCampaignAssetDoc, getCharacterAssetDoc } from "./_getRef";
import { createApiFunction } from "api-calls/createApiFunction";
import { StoredAsset } from "types/Asset.type";
import { AssetDocument } from "api-calls/assets/_asset.type";

export const updateAsset = createApiFunction<
{
characterId?: string;
campaignId?: string;
assetId: string;
asset: PartialWithFieldValue<StoredAsset>;
asset: PartialWithFieldValue<AssetDocument>;
},
void
>((params) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LegacyTrack } from "./LegacyTrack.type";
import { LegacyTrack } from "types/LegacyTrack.type";

export interface StoredCampaign {
export interface CampaignDocument {
name: string;
users: string[];
characters: { uid: string; characterId: string }[];
Expand Down
6 changes: 3 additions & 3 deletions src/api-calls/campaign/_getRef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
doc,
DocumentReference,
} from "firebase/firestore";
import { StoredCampaign } from "types/Campaign.type";
import { CampaignDocument } from "api-calls/campaign/_campaign.type";

export function constructCampaignCollectionPath() {
return `/campaigns`;
Expand All @@ -18,12 +18,12 @@ export function getCampaignCollection() {
return collection(
firestore,
constructCampaignCollectionPath()
) as CollectionReference<StoredCampaign>;
) as CollectionReference<CampaignDocument>;
}

export function getCampaignDoc(campaignId: string) {
return doc(
firestore,
constructCampaignDocPath(campaignId)
) as DocumentReference<StoredCampaign>;
) as DocumentReference<CampaignDocument>;
}
4 changes: 2 additions & 2 deletions src/api-calls/campaign/createCampaign.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addDoc } from "firebase/firestore";
import { supplyTrack } from "../../data/defaultTracks";
import { StoredCampaign } from "../../types/Campaign.type";
import { CampaignDocument } from "../../api-calls/campaign/_campaign.type";
import { getCampaignCollection } from "./_getRef";
import { createApiFunction } from "api-calls/createApiFunction";

Expand All @@ -10,7 +10,7 @@ export const createCampaign = createApiFunction<
>((params) => {
const { uid, campaignName } = params;
return new Promise((resolve, reject) => {
const storedCampaign: StoredCampaign = {
const storedCampaign: CampaignDocument = {
name: campaignName,
users: [uid],
characters: [],
Expand Down
2 changes: 1 addition & 1 deletion src/api-calls/campaign/deleteCampaign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getCharacterDoc } from "../character/_getRef";
import { getCampaignDoc } from "./_getRef";
import { createApiFunction } from "api-calls/createApiFunction";
import { deleteNotes } from "api-calls/notes/deleteNotes";
import { getCampaignSettingsDoc } from "api-calls/custom-move-oracle-settings/_getRef";
import { getCampaignSettingsDoc } from "api-calls/character-campaign-settings/_getRef";
import { deleteAllProgressTracks } from "api-calls/tracks/deleteAllProgressTracks";
import { deleteAllLogs } from "api-calls/game-log/deleteAllLogs";
import { deleteAllAssets } from "api-calls/assets/deleteAllAssets";
Expand Down
4 changes: 2 additions & 2 deletions src/api-calls/campaign/getCampaign.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getDoc } from "firebase/firestore";
import { StoredCampaign } from "types/Campaign.type";
import { CampaignDocument } from "api-calls/campaign/_campaign.type";
import { getCampaignDoc } from "./_getRef";
import { createApiFunction } from "api-calls/createApiFunction";

export const getCampaign = createApiFunction<string, StoredCampaign>(
export const getCampaign = createApiFunction<string, CampaignDocument>(
(campaignId) => {
return new Promise((resolve, reject) => {
getDoc(getCampaignDoc(campaignId))
Expand Down
4 changes: 2 additions & 2 deletions src/api-calls/campaign/leaveCampaign.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { arrayRemove, updateDoc } from "firebase/firestore";
import { StoredCampaign } from "types/Campaign.type";
import { CampaignDocument } from "api-calls/campaign/_campaign.type";
import { getCampaignDoc } from "./_getRef";
import { updateCampaignGM } from "./updateCampaignGM";
import { removeCharacterFromCampaign } from "./removeCharacterFromCampaign";
import { createApiFunction } from "api-calls/createApiFunction";

export const leaveCampaign = createApiFunction<
{ uid: string; campaignId: string; campaign: StoredCampaign },
{ uid: string; campaignId: string; campaign: CampaignDocument },
void
>(async (params) => {
const { uid, campaignId, campaign } = params;
Expand Down
2 changes: 1 addition & 1 deletion src/api-calls/campaign/listenToCampaignCharacters.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { onSnapshot, Unsubscribe } from "firebase/firestore";
import { getCharacterDoc } from "../character/_getRef";
import { CharacterDocument } from "../../types/Character.type";
import { CharacterDocument } from "api-calls/character/_character.type";

interface Params {
characterIdList: string[];
Expand Down
4 changes: 2 additions & 2 deletions src/api-calls/campaign/listenToUsersCampaigns.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { onSnapshot, query, where } from "firebase/firestore";
import { StoredCampaign } from "types/Campaign.type";
import { CampaignDocument } from "api-calls/campaign/_campaign.type";
import { getCampaignCollection } from "./_getRef";

export function listenToUsersCampaigns(
uid: string,
dataHandler: {
onDocChange: (id: string, data: StoredCampaign) => void;
onDocChange: (id: string, data: CampaignDocument) => void;
onDocRemove: (id: string) => void;
onLoaded: () => void;
},
Expand Down
4 changes: 2 additions & 2 deletions src/api-calls/campaign/removeCharacterFromCampaign.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { arrayRemove, deleteField, updateDoc } from "firebase/firestore";
import { arrayRemove, updateDoc } from "firebase/firestore";
import { getCharacterDoc } from "../character/_getRef";
import { getCampaignDoc } from "./_getRef";
import { createApiFunction } from "api-calls/createApiFunction";
Expand All @@ -13,7 +13,7 @@ export const removeCharacterFromCampaign = createApiFunction<
characters: arrayRemove({ characterId, uid }),
});
const characterPromise = updateDoc(getCharacterDoc(characterId), {
campaignId: deleteField(),
campaignId: null,
});

Promise.all([campaignPromise, characterPromise])
Expand Down
4 changes: 2 additions & 2 deletions src/api-calls/campaign/updateCampaign.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { UpdateData, updateDoc } from "firebase/firestore";
import { getCampaignDoc } from "./_getRef";
import { createApiFunction } from "api-calls/createApiFunction";
import { StoredCampaign } from "types/Campaign.type";
import { CampaignDocument } from "api-calls/campaign/_campaign.type";

export const updateCampaign = createApiFunction<
{
campaignId: string;
campaign: UpdateData<StoredCampaign>;
campaign: UpdateData<CampaignDocument>;
},
void
>((params) => {
Expand Down
Loading

0 comments on commit ccd7736

Please sign in to comment.