From 7a40f8abac0b52b9626e4ee1a7a452855ea3c419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Pons?= Date: Tue, 18 Nov 2025 17:54:11 +0100 Subject: [PATCH] WebSocket API, new ID/encrypt/decrypt algorithm. --- app/components/base/DraggableTree.vue | 80 -- app/components/base/DraggableTreeItem.vue | 140 --- app/db/schema.ts | 8 +- app/pages/campaign/[id]/index.client.vue | 4 + app/pages/campaign/index.client.vue | 3 +- app/pages/character/[id]/index.client.vue | 4 + app/types/campaign.d.ts | 2 +- app/types/character.d.ts | 2 + db.sqlite | Bin 761856 -> 761856 bytes drizzle.config.ts | 2 +- drizzle/0023_chunky_thunderbird.sql | 19 + drizzle/0024_secret_arclight.sql | 17 + drizzle/meta/0023_snapshot.json | 1002 ++++++++++++++++++++ drizzle/meta/0024_snapshot.json | 1010 +++++++++++++++++++++ drizzle/meta/_journal.json | 14 + nuxt.config.ts | 1 - server/api/campaign.post.ts | 8 +- server/api/campaign/[id].get.ts | 2 +- server/api/campaign/[id].post.ts | 4 +- server/api/character/[id].get.ts | 4 +- server/routes/ws/campaign/[id].ts | 34 +- server/utils/session.ts | 21 +- shared/campaign.util.ts | 61 +- shared/character.util.ts | 14 +- shared/general.util.ts | 63 +- shared/websocket.util.ts | 77 ++ 26 files changed, 2303 insertions(+), 293 deletions(-) delete mode 100644 app/components/base/DraggableTree.vue delete mode 100644 app/components/base/DraggableTreeItem.vue create mode 100644 drizzle/0023_chunky_thunderbird.sql create mode 100644 drizzle/0024_secret_arclight.sql create mode 100644 drizzle/meta/0023_snapshot.json create mode 100644 drizzle/meta/0024_snapshot.json create mode 100644 shared/websocket.util.ts diff --git a/app/components/base/DraggableTree.vue b/app/components/base/DraggableTree.vue deleted file mode 100644 index 3decca2..0000000 --- a/app/components/base/DraggableTree.vue +++ /dev/null @@ -1,80 +0,0 @@ - - - \ No newline at end of file diff --git a/app/components/base/DraggableTreeItem.vue b/app/components/base/DraggableTreeItem.vue deleted file mode 100644 index 7649ebe..0000000 --- a/app/components/base/DraggableTreeItem.vue +++ /dev/null @@ -1,140 +0,0 @@ - - - \ No newline at end of file diff --git a/app/db/schema.ts b/app/db/schema.ts index c5f4f30..e49a23d 100644 --- a/app/db/schema.ts +++ b/app/db/schema.ts @@ -84,10 +84,10 @@ export const characterChoicesTable = table("character_choices", { export const campaignTable = table("campaign", { id: int().primaryKey({ autoIncrement: true }), name: text().notNull(), - description: text(), owner: int().notNull().references(() => usersTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }), link: text().notNull(), status: text({ enum: ['PREPARING', 'PLAYING', 'ARCHIVED'] }).default('PREPARING'), + settings: text({ mode: 'json' }).default('{}'), inventory: text({ mode: 'json' }).default('[]'), money: int().default(0), public_notes: text().default(''), @@ -103,11 +103,11 @@ export const campaignCharactersTable = table("campaign_characters", { }, (table) => [primaryKey({ columns: [table.id, table.character] })]); export const campaignLogsTable = table("campaign_logs", { id: int().references(() => campaignTable.id, { onDelete: 'cascade', onUpdate: 'cascade' }), - from: int().references(() => campaignCharactersTable.character, { onDelete: 'cascade', onUpdate: 'cascade' }), + target: int().references(() => campaignCharactersTable.character, { onDelete: 'cascade', onUpdate: 'cascade' }), timestamp: int({ mode: 'timestamp_ms' }).notNull(), type: text({ enum: ['ITEM', 'CHARACTER', 'PLACE', 'EVENT', 'FIGHT', 'TEXT'] }), details: text().notNull(), -}, (table) => [primaryKey({ columns: [table.id, table.from, table.timestamp] })]); +}, (table) => [primaryKey({ columns: [table.id, table.target, table.timestamp] })]); export const usersRelation = relations(usersTable, ({ one, many }) => ({ data: one(usersDataTable, { fields: [usersTable.id], references: [usersDataTable.id], }), @@ -166,5 +166,5 @@ export const campaignCharacterRelation = relations(campaignCharactersTable, ({ o })); export const campaignLogsRelation = relations(campaignLogsTable, ({ one }) => ({ campaign: one(campaignTable, { fields: [campaignLogsTable.id], references: [campaignTable.id], }), - character: one(campaignCharactersTable, { fields: [campaignLogsTable.from], references: [campaignCharactersTable.character], }), + character: one(campaignCharactersTable, { fields: [campaignLogsTable.target], references: [campaignCharactersTable.character], }), })); \ No newline at end of file diff --git a/app/pages/campaign/[id]/index.client.vue b/app/pages/campaign/[id]/index.client.vue index 3eb79ed..3b424d6 100644 --- a/app/pages/campaign/[id]/index.client.vue +++ b/app/pages/campaign/[id]/index.client.vue @@ -16,6 +16,10 @@ onMounted(() => { { const campaign = new CampaignSheet(id, user); container.value.appendChild(campaign.container); + + onUnmounted(() => { + campaign.ws?.close(); + }) } }); }) diff --git a/app/pages/campaign/index.client.vue b/app/pages/campaign/index.client.vue index 325f7f1..6401da4 100644 --- a/app/pages/campaign/index.client.vue +++ b/app/pages/campaign/index.client.vue @@ -38,7 +38,7 @@ function create() { useRequestFetch()('/api/campaign', { method: 'POST', - body: { id: 'new', name: 'Test', description: '', joinby: 'link' }, + body: { name: 'Margooning', public_notes: '', dm_notes: '', settings: {} }, }).then(() => Toaster.add({ duration: 8000, content: 'Campagne créée', type: 'info' })).catch((e) => Toaster.add({ duration: 8000, title: 'Une erreur est survenue', content: e, type: 'error' })) } @@ -52,6 +52,7 @@ function create()