diff --git a/src/models/story-events.ts b/src/models/story-events.ts index 7bc37bc..ba5f028 100644 --- a/src/models/story-events.ts +++ b/src/models/story-events.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { knex } from "@db/index"; +import { knex } from '@db/index'; import { omit } from 'lodash'; /** @@ -60,86 +60,104 @@ export const StoryEventMessagesLink = z.object({ export type StoryEventMessagesLink = z.infer; export const StoryEventWithRelations = StoryEvent.extend({ - artifacts: z.array(z.object({ - id: z.number(), - catalog_id: z.string(), - name: z.string(), - })), - messages: z.array(z.object({ - id: z.number(), - name: z.string(), - sent: z.string(), - })), - persons: z.array(z.object({ - id: z.string(), - name: z.string(), - is_character: z.boolean(), - })), - plots: z.array(z.object({ - id: z.number(), - name: z.string(), - })), + artifacts: z.array( + z.object({ + id: z.number(), + catalog_id: z.string(), + name: z.string(), + }) + ), + messages: z.array( + z.object({ + id: z.number(), + name: z.string(), + sent: z.string(), + }) + ), + persons: z.array( + z.object({ + id: z.string(), + name: z.string(), + is_character: z.boolean(), + }) + ), + plots: z.array( + z.object({ + id: z.number(), + name: z.string(), + }) + ), }); export type StoryEventWithRelations = z.infer; export const listStoryEvents = async (): Promise => { const events = await knex('story_events').select('*'); - const events_with_persons = await Promise.all(events.map(async event => { - const [artifacts, persons, messages, plots] = await Promise.all([ - knex('story_artifact_events') - .join('artifact', 'story_artifact_events.artifact_id', 'artifact.id') - .select('artifact.name', 'artifact.id', 'artifact.catalog_id') - .where({ event_id: event.id }), - knex('story_person_events') - .join('person', 'story_person_events.person_id', 'person.id') - .select('person.id', 'person.is_character', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as name')) - .where({ event_id: event.id }), - knex('story_event_messages') - .join('story_messages', 'story_event_messages.message_id', 'story_messages.id') - .select('story_messages.id', 'story_messages.name', 'story_messages.sent') - .where({ event_id: event.id }), - knex('story_event_plots') - .join('story_plots', 'story_event_plots.plot_id', 'story_plots.id') - .select('story_plots.id', 'story_plots.name') - .where({ event_id: event.id }), - ]); + const events_with_persons = await Promise.all( + events.map(async event => { + const [artifacts, persons, messages, plots] = await Promise.all([ + knex('story_artifact_events') + .join('artifact', 'story_artifact_events.artifact_id', 'artifact.id') + .select('artifact.name', 'artifact.id', 'artifact.catalog_id') + .where({ event_id: event.id }), + knex('story_person_events') + .join('person', 'story_person_events.person_id', 'person.id') + .select( + 'person.id', + 'person.is_character', + knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as name") + ) + .where({ event_id: event.id }), + knex('story_event_messages') + .join('story_messages', 'story_event_messages.message_id', 'story_messages.id') + .select('story_messages.id', 'story_messages.name', 'story_messages.sent') + .where({ event_id: event.id }), + knex('story_event_plots') + .join('story_plots', 'story_event_plots.plot_id', 'story_plots.id') + .select('story_plots.id', 'story_plots.name') + .where({ event_id: event.id }), + ]); - return StoryEventWithRelations.parse({ - ...event, - artifacts, - persons, - messages, - plots, - }); - })); + return StoryEventWithRelations.parse({ + ...event, + artifacts, + persons, + messages, + plots, + }); + }) + ); - return events_with_persons; -} + return events_with_persons; +}; export const getStoryEvent = async (id: number): Promise => { - const event = await knex('story_events').select('*').where({ id }).first() + const event = await knex('story_events').select('*').where({ id }).first(); if (!event) { return null; } const [artifacts, persons, messages, plots] = await Promise.all([ knex('story_artifact_events') - .join('artifact', 'story_artifact_events.artifact_id', 'artifact.id') - .select('artifact.name', 'artifact.id', 'artifact.catalog_id') - .where({ event_id: id }), + .join('artifact', 'story_artifact_events.artifact_id', 'artifact.id') + .select('artifact.name', 'artifact.id', 'artifact.catalog_id') + .where({ event_id: id }), knex('story_person_events') - .join('person', 'story_person_events.person_id', 'person.id') - .select('person.id', 'person.is_character', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as name')) - .where({ event_id: id }), + .join('person', 'story_person_events.person_id', 'person.id') + .select( + 'person.id', + 'person.is_character', + knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as name") + ) + .where({ event_id: id }), knex('story_event_messages') - .join('story_messages', 'story_event_messages.message_id', 'story_messages.id') - .select('story_messages.id', 'story_messages.name', 'story_messages.sent') - .where({ event_id: id }), + .join('story_messages', 'story_event_messages.message_id', 'story_messages.id') + .select('story_messages.id', 'story_messages.name', 'story_messages.sent') + .where({ event_id: id }), knex('story_event_plots') - .join('story_plots', 'story_event_plots.plot_id', 'story_plots.id') - .select('story_plots.id', 'story_plots.name') - .where({ event_id: id }), + .join('story_plots', 'story_event_plots.plot_id', 'story_plots.id') + .select('story_plots.id', 'story_plots.name') + .where({ event_id: id }), ]); return StoryEventWithRelations.parse({ @@ -149,7 +167,7 @@ export const getStoryEvent = async (id: number): Promise; export async function upsertStoryEvent(event: StoryEventCreate): Promise { - const trx = await knex.transaction(); - const evt = omit(event, ['artifacts', 'persons', 'plots', 'messages']); - const [{ id }] = await trx('story_events').insert(evt).onConflict('id').merge().returning('id'); - await trx('story_artifact_events').where({ event_id: id }).delete(); - await trx('story_person_events').where({ event_id: id }).delete(); - await trx('story_event_messages').where({ event_id: id }).delete(); - await trx('story_event_plots').where({ event_id: id }).delete(); - if (event.artifacts && event.artifacts.length > 0) { - await trx('story_artifact_events').insert(event.artifacts.map((artifact_id) => ({ event_id: id, artifact_id }))); - } - if (event.persons && event.persons.length > 0) { - await trx('story_person_events').insert(event.persons.map((person_id) => ({ event_id: id, person_id }))); - } - if (event.messages && event.messages.length > 0) { - await trx('story_event_messages').insert(event.messages.map((message_id) => ({ event_id: id, message_id }))); - } - if (event.plots && event.plots.length > 0) { - await trx('story_event_plots').insert(event.plots.map((plot_id) => ({ event_id: id, plot_id }))); - } - await trx.commit(); - return id; + return await knex.transaction(async trx => { + const evt = omit(event, ['artifacts', 'persons', 'plots', 'messages']); + const [{ id }] = await trx('story_events').insert(evt).onConflict('id').merge().returning('id'); + await trx('story_artifact_events').where({ event_id: id }).delete(); + await trx('story_person_events').where({ event_id: id }).delete(); + await trx('story_event_messages').where({ event_id: id }).delete(); + await trx('story_event_plots').where({ event_id: id }).delete(); + if (event.artifacts && event.artifacts.length > 0) { + await trx('story_artifact_events').insert(event.artifacts.map(artifact_id => ({ event_id: id, artifact_id }))); + } + if (event.persons && event.persons.length > 0) { + await trx('story_person_events').insert(event.persons.map(person_id => ({ event_id: id, person_id }))); + } + if (event.messages && event.messages.length > 0) { + await trx('story_event_messages').insert(event.messages.map(message_id => ({ event_id: id, message_id }))); + } + if (event.plots && event.plots.length > 0) { + await trx('story_event_plots').insert(event.plots.map(plot_id => ({ event_id: id, plot_id }))); + } + return id; + }); } diff --git a/src/models/story-messages.ts b/src/models/story-messages.ts index d0a411f..8c7b7cc 100644 --- a/src/models/story-messages.ts +++ b/src/models/story-messages.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { knex } from "@db/index"; +import { knex } from '@db/index'; import { omit } from 'lodash'; /** @@ -34,49 +34,67 @@ export const StoryMessagePersonLink = z.object({ export type StoryMessagePersonLink = z.infer; export const StoryMessageWithRelations = StoryMessage.extend({ - events: z.array(z.object({ - id: z.number(), - name: z.string(), - })), - plots: z.array(z.object({ - id: z.number(), - name: z.string(), - })), - receivers: z.array(z.object({ - card_id: z.string().optional(), - id: z.string(), - name: z.string(), - is_character: z.boolean(), - })), - sender: z.object({ - card_id: z.string().optional(), - id: z.string(), - name: z.string(), - is_character: z.boolean(), - }).or(z.null()), + events: z.array( + z.object({ + id: z.number(), + name: z.string(), + }) + ), + plots: z.array( + z.object({ + id: z.number(), + name: z.string(), + }) + ), + receivers: z.array( + z.object({ + card_id: z.string().optional(), + id: z.string(), + name: z.string(), + is_character: z.boolean(), + }) + ), + sender: z + .object({ + card_id: z.string().optional(), + id: z.string(), + name: z.string(), + is_character: z.boolean(), + }) + .or(z.null()), }); export type StoryMessageWithRelations = z.infer; export const StoryMessageWithPersons = StoryMessage.extend({ - receivers: z.array(z.object({ - id: z.string(), - name: z.string(), - })), - sender: z.object({ - id: z.string(), - name: z.string(), - }).or(z.null()), + receivers: z.array( + z.object({ + id: z.string(), + name: z.string(), + }) + ), + sender: z + .object({ + id: z.string(), + name: z.string(), + }) + .or(z.null()), }); export type StoryMessageWithPersons = z.infer; export async function listStoryMessages(): Promise { - const messages = await knex('story_messages').select('story_messages.*', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as sender_name')).leftJoin('person', 'story_messages.sender_person_id', 'person.id') - const storyPersonMessage = await knex('story_person_messages').select('story_person_messages.*', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as name')).join('person', 'story_person_messages.person_id', 'person.id') + const messages = await knex('story_messages') + .select('story_messages.*', knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as sender_name")) + .leftJoin('person', 'story_messages.sender_person_id', 'person.id'); + const storyPersonMessage = await knex('story_person_messages') + .select('story_person_messages.*', knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as name")) + .join('person', 'story_person_messages.person_id', 'person.id'); messages.forEach(message => { - const receivers = storyPersonMessage.filter(({ message_id }) => message.id === message_id).map(({ person_id, name }) => ({ id: person_id, name })); + const receivers = storyPersonMessage + .filter(({ message_id }) => message.id === message_id) + .map(({ person_id, name }) => ({ id: person_id, name })); message.receivers = receivers; if (message.sender_person_id) { - message.sender = { + message.sender = { id: message.sender_person_id, name: message.sender_name, }; @@ -88,24 +106,38 @@ export async function listStoryMessages(): Promise { } export async function getStoryMessage(id: number): Promise { - const message = await knex('story_messages').select('story_messages.*', 'person.card_id', 'person.is_character', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as sender_name')).leftJoin('person', 'story_messages.sender_person_id', 'person.id').where('story_messages.id', "=", id).first(); + const message = await knex('story_messages') + .select( + 'story_messages.*', + 'person.card_id', + 'person.is_character', + knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as sender_name") + ) + .leftJoin('person', 'story_messages.sender_person_id', 'person.id') + .where('story_messages.id', '=', id) + .first(); if (!message) { return null; } const [events, receivers, plots] = await Promise.all([ knex('story_event_messages') - .join('story_events', 'story_event_messages.event_id', 'story_events.id') - .select('story_events.id', 'story_events.name') - .where({ message_id: id }), + .join('story_events', 'story_event_messages.event_id', 'story_events.id') + .select('story_events.id', 'story_events.name') + .where({ message_id: id }), knex('story_person_messages') - .join('person', 'story_person_messages.person_id', 'person.id') - .select('person.id', 'person.card_id', 'person.is_character', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as name')) - .where({ message_id: id }), + .join('person', 'story_person_messages.person_id', 'person.id') + .select( + 'person.id', + 'person.card_id', + 'person.is_character', + knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as name") + ) + .where({ message_id: id }), knex('story_plot_messages') - .join('story_plots', 'story_plot_messages.plot_id', 'story_plots.id') - .select('story_plots.id', 'story_plots.name') - .where({ message_id: id }), + .join('story_plots', 'story_plot_messages.plot_id', 'story_plots.id') + .select('story_plots.id', 'story_plots.name') + .where({ message_id: id }), ]); return StoryMessageWithRelations.parse({ @@ -113,12 +145,14 @@ export async function getStoryMessage(id: number): Promise; export async function upsertStoryMessage(message: StoryMessageCreate): Promise { - const trx = await knex.transaction(); - const msg = omit(message, ['receivers', 'events', 'plots']); - const [{ id }] = await trx('story_messages').insert(msg).onConflict('id').merge().returning('id'); - await trx('story_person_messages').where({ message_id: id }).delete(); - if (message.receivers && message.receivers.length > 0) { - await trx('story_person_messages').insert(message.receivers.map((person_id) => ({ message_id: id, person_id }))); - } - await trx('story_event_messages').where({ message_id: id }).delete(); - if (message.events && message.events.length > 0) { - await trx('story_event_messages').insert(message.events.map((event_id) => ({ message_id: id, event_id }))); - } - await trx('story_plot_messages').where({ message_id: id }).delete(); - if (message.plots && message.plots.length > 0) { - await trx('story_plot_messages').insert(message.plots.map((plot_id) => ({ message_id: id, plot_id }))); - } - await trx.commit(); - return id; + return await knex.transaction(async trx => { + const msg = omit(message, ['receivers', 'events', 'plots']); + const [{ id }] = await trx('story_messages').insert(msg).onConflict('id').merge().returning('id'); + await trx('story_person_messages').where({ message_id: id }).delete(); + if (message.receivers && message.receivers.length > 0) { + await trx('story_person_messages').insert(message.receivers.map(person_id => ({ message_id: id, person_id }))); + } + await trx('story_event_messages').where({ message_id: id }).delete(); + if (message.events && message.events.length > 0) { + await trx('story_event_messages').insert(message.events.map(event_id => ({ message_id: id, event_id }))); + } + await trx('story_plot_messages').where({ message_id: id }).delete(); + if (message.plots && message.plots.length > 0) { + await trx('story_plot_messages').insert(message.plots.map(plot_id => ({ message_id: id, plot_id }))); + } + return id; + }); } diff --git a/src/models/story-plots.ts b/src/models/story-plots.ts index f7372d3..e85b6f3 100644 --- a/src/models/story-plots.ts +++ b/src/models/story-plots.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { knex } from "@db/index"; +import { knex } from '@db/index'; import { omit } from 'lodash'; /** @@ -60,62 +60,76 @@ export const StoryPlotMessagesLink = z.object({ export type StoryPlotMessagesLink = z.infer; export const StoryPlotWithRelations = StoryPlot.extend({ - artifacts: z.array(z.object({ - id: z.number(), - name: z.string(), - catalog_id: z.string(), - })), - events: z.array(z.object({ - id: z.number(), - name: z.string(), - })), - messages: z.array(z.object({ - id: z.number(), - name: z.string(), - sent: z.string(), - })), - persons: z.array(z.object({ - id: z.string(), - name: z.string(), - is_character: z.boolean(), - })), + artifacts: z.array( + z.object({ + id: z.number(), + name: z.string(), + catalog_id: z.string(), + }) + ), + events: z.array( + z.object({ + id: z.number(), + name: z.string(), + }) + ), + messages: z.array( + z.object({ + id: z.number(), + name: z.string(), + sent: z.string(), + }) + ), + persons: z.array( + z.object({ + id: z.string(), + name: z.string(), + is_character: z.boolean(), + }) + ), }); export type StoryPlotWithRelations = z.infer; export async function listStoryPlots(): Promise { const plots = await knex('story_plots').select('*'); - const plots_with_persons = await Promise.all(plots.map(async plot => { - const [artifacts, events, messages, persons] = await Promise.all([ - knex('story_artifact_plots') - .join('artifact', 'story_artifact_plots.artifact_id', 'artifact.id') - .select('artifact.name', 'artifact.id', 'artifact.catalog_id') - .where({ plot_id: plot.id }), - knex('story_event_plots') - .join('story_events', 'story_event_plots.event_id', 'story_events.id') - .select('story_events.id', 'story_events.name') - .where({ plot_id: plot.id }), - knex('story_plot_messages') - .join('story_messages', 'story_plot_messages.message_id', 'story_messages.id') - .select('story_messages.id', 'story_messages.sent', 'story_messages.name') - .where({ plot_id: plot.id }), - knex('story_person_plots') - .join('person', 'story_person_plots.person_id', 'person.id') - .select('person.id', 'person.is_character', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as name')) - .where({ plot_id: plot.id }), - ]); + const plots_with_persons = await Promise.all( + plots.map(async plot => { + const [artifacts, events, messages, persons] = await Promise.all([ + knex('story_artifact_plots') + .join('artifact', 'story_artifact_plots.artifact_id', 'artifact.id') + .select('artifact.name', 'artifact.id', 'artifact.catalog_id') + .where({ plot_id: plot.id }), + knex('story_event_plots') + .join('story_events', 'story_event_plots.event_id', 'story_events.id') + .select('story_events.id', 'story_events.name') + .where({ plot_id: plot.id }), + knex('story_plot_messages') + .join('story_messages', 'story_plot_messages.message_id', 'story_messages.id') + .select('story_messages.id', 'story_messages.sent', 'story_messages.name') + .where({ plot_id: plot.id }), + knex('story_person_plots') + .join('person', 'story_person_plots.person_id', 'person.id') + .select( + 'person.id', + 'person.is_character', + knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as name") + ) + .where({ plot_id: plot.id }), + ]); - return StoryPlotWithRelations.parse({ - ...plot, - persons, - artifacts, - messages, - events, - }); - })); + return StoryPlotWithRelations.parse({ + ...plot, + persons, + artifacts, + messages, + events, + }); + }) + ); return plots_with_persons; -}; +} export async function getStoryPlot(id: number): Promise { const plot = await knex('story_plots').select('*').where({ id }).first(); @@ -125,21 +139,25 @@ export async function getStoryPlot(id: number): Promise { const [artifacts, events, messages, persons] = await Promise.all([ knex('story_artifact_plots') - .join('artifact', 'story_artifact_plots.artifact_id', 'artifact.id') - .select('artifact.name', 'artifact.id', 'artifact.catalog_id') - .where({ plot_id: id }), + .join('artifact', 'story_artifact_plots.artifact_id', 'artifact.id') + .select('artifact.name', 'artifact.id', 'artifact.catalog_id') + .where({ plot_id: id }), knex('story_event_plots') - .join('story_events', 'story_event_plots.event_id', 'story_events.id') - .select('story_events.id', 'story_events.name') - .where({ plot_id: id }), + .join('story_events', 'story_event_plots.event_id', 'story_events.id') + .select('story_events.id', 'story_events.name') + .where({ plot_id: id }), knex('story_plot_messages') - .join('story_messages', 'story_plot_messages.message_id', 'story_messages.id') - .select('story_messages.id', 'story_messages.sent', 'story_messages.name') - .where({ plot_id: id }), + .join('story_messages', 'story_plot_messages.message_id', 'story_messages.id') + .select('story_messages.id', 'story_messages.sent', 'story_messages.name') + .where({ plot_id: id }), knex('story_person_plots') - .join('person', 'story_person_plots.person_id', 'person.id') - .select('person.id', 'person.is_character', knex.raw('TRIM(CONCAT(person.first_name, \' \', person.last_name)) as name')) - .where({ plot_id: id }), + .join('person', 'story_person_plots.person_id', 'person.id') + .select( + 'person.id', + 'person.is_character', + knex.raw("TRIM(CONCAT(person.first_name, ' ', person.last_name)) as name") + ) + .where({ plot_id: id }), ]); return StoryPlotWithRelations.parse({ @@ -161,25 +179,25 @@ export const StoryPlotCreate = StoryPlot.extend({ export type StoryPlotCreate = z.infer; export async function upsertStoryPlot(plot: StoryPlotCreate): Promise { - const trx = await knex.transaction(); - const plainPlot = omit(plot, ['artifacts', 'persons', 'events', 'messages']); - const [{ id }] = await trx('story_plots').insert(plainPlot).onConflict('id').merge().returning('id'); - await trx('story_artifact_plots').where({ plot_id: id }).delete(); - await trx('story_event_plots').where({ plot_id: id }).delete(); - await trx('story_plot_messages').where({ plot_id: id }).delete(); - await trx('story_person_plots').where({ plot_id: id }).delete(); - if (plot.artifacts && plot.artifacts.length > 0) { - await trx('story_artifact_plots').insert(plot.artifacts.map((artifact_id) => ({ plot_id: id, artifact_id }))); - } - if (plot.events && plot.events.length > 0) { - await trx('story_event_plots').insert(plot.events.map((event_id) => ({ plot_id: id, event_id }))); - } - if (plot.messages && plot.messages.length > 0) { - await trx('story_plot_messages').insert(plot.messages.map((message_id) => ({ plot_id: id, message_id }))); - } - if (plot.persons && plot.persons.length > 0) { - await trx('story_person_plots').insert(plot.persons.map((person_id) => ({ plot_id: id, person_id }))); - } - await trx.commit(); - return id; + return await knex.transaction(async trx => { + const plainPlot = omit(plot, ['artifacts', 'persons', 'events', 'messages']); + const [{ id }] = await trx('story_plots').insert(plainPlot).onConflict('id').merge().returning('id'); + await trx('story_artifact_plots').where({ plot_id: id }).delete(); + await trx('story_event_plots').where({ plot_id: id }).delete(); + await trx('story_plot_messages').where({ plot_id: id }).delete(); + await trx('story_person_plots').where({ plot_id: id }).delete(); + if (plot.artifacts && plot.artifacts.length > 0) { + await trx('story_artifact_plots').insert(plot.artifacts.map(artifact_id => ({ plot_id: id, artifact_id }))); + } + if (plot.events && plot.events.length > 0) { + await trx('story_event_plots').insert(plot.events.map(event_id => ({ plot_id: id, event_id }))); + } + if (plot.messages && plot.messages.length > 0) { + await trx('story_plot_messages').insert(plot.messages.map(message_id => ({ plot_id: id, message_id }))); + } + if (plot.persons && plot.persons.length > 0) { + await trx('story_person_plots').insert(plot.persons.map(person_id => ({ plot_id: id, person_id }))); + } + return id; + }); }