Skip to content

docs(core): guide on saving an instance and some of its relations #4

@paul-thebaud

Description

@paul-thebaud

What problem is this solving

Foscia may be used to save an instance and its related models (to many) by using a diff between $original and current values. It should be listed inside the "Guides > Models" documentation.

Proposed solution

Here is an example of a working code on another which should be made generic:

import action from '@/ts/api/action';
import fillAndSave from '@/ts/api/utilities/fillAndSave';
import hardDelete from '@/ts/api/utilities/hardDelete';
import wrap from '@/ts/utilities/arrays/wrap';
import { Arrayable } from '@/ts/utilities/types/arrayable';
import { Awaitable } from '@/ts/utilities/types/awaitable';
import { changed, ModelInstance, oneOrCurrent, save, when } from 'foscia/core';

export type SaveWithRelationsOptions = {
  prepareRelated?: (
    context: { instance: ModelInstance, relation: string, related: ModelInstance },
  ) => Awaitable<void>;
};

export default async function saveWithRelations(
  instance: ModelInstance,
  relations: Arrayable<string>,
  options: SaveWithRelationsOptions = {},
) {
  const relationsValues = relations.map((relation) => ({
    relation,
    prev: [...wrap(instance.$original.$values[relation])],
    next: [...wrap(instance.$values[relation])],
  }));

  await fillAndSave(instance, {});

  await Promise.all(relationsValues.map(async (relation) => {
    await Promise.all(relation.next.map(
      (nextModel) => action()
        .use(when(() => options.prepareRelated, async (_, callback) => {
          await callback({
            instance, relation, related: nextModel,
          });
        }))
        .use(save(nextModel))
        .run(when(!nextModel.exists || changed(nextModel), oneOrCurrent(), () => nextModel)),
    ));

    await Promise.all(
      relation.prev
        .filter((prevModel) => relation.next.indexOf(prevModel) === -1)
        .map((prevModel) => hardDelete(prevModel)),
    );
  }));
}

Describe alternatives you've considered

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority:lowMay be addressed at any timescope:core@foscia/coretype:docsImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions