feat: add TypeScript type checking task to VSCode configuration

feat: implement area metadata blocks in game commands for enhanced area details

fix: refactor game commands to utilize new area metadata blocks and improve code consistency

feat: enhance Appwrite API integration with additional collections and storage support

refactor: update componentsV2 to support image blocks in display rendering
This commit is contained in:
2025-10-07 22:17:03 -05:00
parent 5ea9cfd67c
commit 67643595f3
9 changed files with 572 additions and 215 deletions

View File

@@ -1,6 +1,6 @@
// Simple Appwrite client wrapper
// @ts-ignore
import { Client, Databases } from "node-appwrite";
import { Client, Databases, Storage } from "node-appwrite";
const endpoint = process.env.APPWRITE_ENDPOINT || "";
const projectId = process.env.APPWRITE_PROJECT_ID || "";
@@ -14,8 +14,21 @@ export const APPWRITE_COLLECTION_AI_CONVERSATIONS_ID =
export const APPWRITE_COLLECTION_GUILD_CACHE_ID =
process.env.APPWRITE_COLLECTION_GUILD_CACHE_ID || "";
// Optional: collections for game realtime mirrors
export const APPWRITE_COLLECTION_QUESTS_ID =
process.env.APPWRITE_COLLECTION_QUESTS_ID || "";
export const APPWRITE_COLLECTION_QUEST_PROGRESS_ID =
process.env.APPWRITE_COLLECTION_QUEST_PROGRESS_ID || "";
export const APPWRITE_COLLECTION_SCHEDULED_ATTACKS_ID =
process.env.APPWRITE_COLLECTION_SCHEDULED_ATTACKS_ID || "";
// Optional: bucket for images (areas/levels)
export const APPWRITE_BUCKET_IMAGES_ID =
process.env.APPWRITE_BUCKET_IMAGES_ID || "";
let client: Client | null = null;
let databases: Databases | null = null;
let storage: Storage | null = null;
function ensureClient() {
if (!endpoint || !projectId || !apiKey) return null;
@@ -25,6 +38,7 @@ function ensureClient() {
.setProject(projectId)
.setKey(apiKey);
databases = new Databases(client);
storage = new Storage(client);
return client;
}
@@ -32,6 +46,10 @@ export function getDatabases(): Databases | null {
return ensureClient() ? (databases as Databases) : null;
}
export function getStorage(): Storage | null {
return ensureClient() ? (storage as Storage) : null;
}
export function isAppwriteConfigured(): boolean {
return Boolean(
endpoint &&
@@ -61,3 +79,20 @@ export function isGuildCacheConfigured(): boolean {
APPWRITE_COLLECTION_GUILD_CACHE_ID
);
}
export function isAppwriteStorageConfigured(): boolean {
return Boolean(endpoint && projectId && apiKey && APPWRITE_BUCKET_IMAGES_ID);
}
export function isGameRealtimeConfigured(): boolean {
// minimal check for quests/progress and scheduled attacks mirrors
return Boolean(
endpoint &&
projectId &&
apiKey &&
APPWRITE_DATABASE_ID &&
(APPWRITE_COLLECTION_QUESTS_ID ||
APPWRITE_COLLECTION_QUEST_PROGRESS_ID ||
APPWRITE_COLLECTION_SCHEDULED_ATTACKS_ID)
);
}

View File

@@ -1,11 +1,17 @@
export type DisplayBlock =
| { kind: 'text'; content: string }
| { kind: 'divider'; divider?: boolean; spacing?: number };
| { kind: "text"; content: string }
| { kind: "divider"; divider?: boolean; spacing?: number }
| { kind: "image"; url: string };
export const textBlock = (content: string): DisplayBlock => ({ kind: 'text', content });
export const textBlock = (content: string): DisplayBlock => ({
kind: "text",
content,
});
export const dividerBlock = (options: { divider?: boolean; spacing?: number } = {}): DisplayBlock => ({
kind: 'divider',
export const dividerBlock = (
options: { divider?: boolean; spacing?: number } = {}
): DisplayBlock => ({
kind: "divider",
divider: options.divider,
spacing: options.spacing,
});
@@ -15,10 +21,15 @@ export function buildDisplay(accentColor: number, blocks: DisplayBlock[]) {
type: 17 as const,
accent_color: accentColor,
components: blocks.map((block) => {
if (block.kind === 'text') {
if (block.kind === "text") {
return { type: 10 as const, content: block.content };
}
if (block.kind === "image") {
// This component type will be translated by the renderer to an embed image
return { type: 12 as const, url: block.url } as any;
}
return {
type: 14 as const,
divider: block.divider ?? true,