castore icon indicating copy to clipboard operation
castore copied to clipboard

Prevent double declaration of store in commands

Open CorentinDoue opened this issue 10 months ago • 0 comments

The command exemple

import { Command, tuple } from '@castore/core';
import { pokemonsEventStore, trainersEventStore } from './stores';

type Input = { name: string; level: number };
type Output = { pokemonId: string };
type Context = { generateUuid: () => string };

const catchPokemonCommand = new Command({
  commandId: 'CATCH_POKEMON',
  // 👇 "tuple" is needed to keep ordering in inferred type
  requiredEventStores: tuple(pokemonsEventStore, trainersEventStore),
  // 👇 Code to execute
  handler: async (
    commandInput: Input,
    [pokemonsEventStore, trainersEventStore],
    // 👇 Additional context arguments can be provided
    { generateUuid }: Context,
  ): Promise<Output> => {
    const { name, level } = commandInput;
    const pokemonId = generateUuid();

    await pokemonsEventStore.pushEvent({
      aggregateId: pokemonId,
      version: 1,
      type: 'POKEMON_CAUGHT',
      payload: { name, level },
    });

    return { pokemonId };
  },
});

makes you create two variable with the same name:

import { pokemonsEventStore, trainersEventStore } from './stores';

and

 handler: async (
    commandInput: Input,
    [pokemonsEventStore, trainersEventStore],
    { generateUuid }: Context,
  )

This trigger @typescript-eslint/no-shadow eslint error and is a bad practise.

I don't know how to name them distinctly because they are the same.

I worked arround with

import { pokemonsEventStore as _pokemonsEventStore, trainersEventStore as _trainersEventStore } from './stores';

but I'm not satisfied.

And in fact the Command does nothing with it and only pass them to the handler. I did find any other usage in the Castore code. What is the usage of this input ?

Can you help me to name them better and if possible remove the need of passing them.

import { Command } from '@castore/core';
import { pokemonsEventStore, trainersEventStore } from './stores';

type Input = { name: string; level: number };
type Output = { pokemonId: string };
type Context = { generateUuid: () => string };

const catchPokemonCommand = new Command({
  commandId: 'CATCH_POKEMON',
  // 👇 Code to execute
  handler: async (
    commandInput: Input,
    // 👇 Additional context arguments can be provided
    { generateUuid }: Context,
  ): Promise<Output> => {
    const { name, level } = commandInput;
    const pokemonId = generateUuid();

    await pokemonsEventStore.pushEvent({
      aggregateId: pokemonId,
      version: 1,
      type: 'POKEMON_CAUGHT',
      payload: { name, level },
    });

    return { pokemonId };
  },
});

This seems to work, no ? It removes the need of tuple and is lighter

CorentinDoue avatar Apr 19 '25 12:04 CorentinDoue