8.4.0 • Published 4 months ago

@feinarbyte/atom-module v8.4.0

Weekly downloads
-
License
UNLICENSED
Repository
-
Last release
4 months ago

Atoms Framework

The Atoms Framework is a state management library designed to manage your application's state in a predictable way. It's based on the concept of "atoms", which are units of state that can be read and written to. Key Concepts

  1. Atoms: Atoms represent pieces of state in your application. They are the smallest units of state that can be read and written to. Atoms are defined in the backend and can be subscribed to in realtime using the useAtom hook.

  2. Context: All atoms live in a certain context. Context is automatically provided in the frontend using the useContext hook. Context is automatically provided to all api calls and all subscriptions.

  3. Reducers: The application is modified through reducers. Each reducers get the transaction as first argument and can specify an arbitrary number of other arguments.

  4. Project Config: The Project Config is a configuration for the project that specifies the atoms, relations, and reducers used in the application.

  5. Relations: Relations define how different atoms are related to each other.

Project Config

The Project Config is a configuration for the project that specifies the atoms, relations, and reducers used in the application.

export const AIConfig: ProjectConfig<AIAtoms, AIContext, AIRelations> = {
  atomIndex: {
    [AIAtoms.Todo]: TodoAtom,
    // other atoms...
  },
  relations: {
    [AIRelations.Todo]: {
      identifier: AIContext.TodoId,
      identifierType: 'string',
      parents: [],
      pathes(name) {
        return [`t/${AIContext.TodoId}/${name}`];
      },
      reducers: [createTodo, toggleTodo, deleteTodo],
    },
    // other relations...
  },
};

The ProjectConfig is defined by the AIAtoms, AIContext, and AIRelations enums. The AIAtoms enum represents the atoms in the application, which are the smallest units of state that can be read and written to. The AIContext enum represents the context in which all atoms live. This context is automatically provided in the frontend using the useContext hook and is automatically provided to all API calls and all subscriptions. The AIRelations enum defines are abstract entites like users. Each atom must belong to one of them. The entites can have hierarchical relations to each other, which are defined in the parents property. The pathes property defines the pathes in the database where the data for this relation is stored. The reducers property defines the reducers that can be used to update the state of the atoms in this relation.

Defining Atoms

Atoms are defined as classes with the @ActiveAtom decorator. They represent a piece of state in your application.

export interface ITodo {
  id: string;
  text: string;
  completed: boolean;
}

@ActiveAtom({
  relation: AIRelations.Todo,
  provideViaAtomResolver: (context, data): ITodo => {
    return data;
  },
})
export class TodoAtom extends Atom<AIAtoms.Todo, ITodo> implements ITodo {
  public readonly __type = AIAtoms.Todo;
  public id: string;
  public text: string;
  public completed: boolean;
}

Virtual Atoms

Virtual atoms are a special kind of atom that do not directly represent a piece of state, but instead derive their state from other atoms. They are defined as classes with the @ActiveAtom decorator, similar to regular atoms, but they extend the VirtualAtom class instead of the Atom class.

Here is an example of a virtual atom:

@ActiveAtom({
  // Defines the relation for this virtual atom
  relation: AIRelations.Tag,
  // Resolver function to provide data for this virtual atom
  provideViaAtomResolver: (context, data): ITag => {
    return data;
  },
})
// TagAtom is a virtual atom that derives its state from other atoms
export class TagAtom extends VirtualAtom<AIAtoms.Tag, ITag> implements ITag {
  // The type of this atom, used for identification
  public readonly __type = AIAtoms.Tag;
  // The entries for this atom, derived from other atoms
  public entries: { [entryId: string]: string };

  // Dependencies of this virtual atom, used to derive its state
  public static dependencies = [
    {
      // The EntryAtom dependency, from which this virtual atom derives its state
      ctor: EntryAtom,
      // Function to get context overrides from the EntryAtom dependency
      getContextOverridesFromDependency: (data: IEntry) => {
        return data.tags.map((tag) => ({ [AIContext.Tag]: tag }));
      },
    },
  ];

  // Function to handle changes in dependencies
  public async __onDependencyChange(
    _query: string,
    newValue: IEntry,
  ): Promise<void> {
    const entryId = this.__getContextEntry(AIContext.EntryId);
    this.entries[entryId] = newValue.title ?? (entryId as string);
  }
  // Function to handle deletion of entities
  __onEntityDelete(relation: string, id: string): Promise<void> {
    delete this.entries[id];
  }

  // Function to provide an empty value when no data is available
  protected override __provideEmptyValue(): ITag {
    return { entries: {} };
  }
}

Defining Reducers in the backend

Reducers are functions that specify how the application's state changes in response to actions. They are used to handle and update the state of an atom.

export async function createTodo(
  transaction: TransactionManager,
  text: string,
): Promise<string> {
  const todoId = Math.random().toString(36).substring(2, 15);
  transaction.setEntry(AIContext.TodoId, todoId);
  await transaction.spawnAtom(
    TodoAtom,
    {
      id: todoId,
      text,
      completed: false,
    },
    { [AIContext.TodoId]: todoId },
  );
  return todoId;
}

Accessing reducers in the frontend

there is a helper to create a hook that provides the api client to the frontend. The api client will group all reducers by relation and provide them as async functions that automatically trigger the reducer in the backend. The context is automatically passed to the reducer.

import { makeUseApiClient } from '@feinarbyte/atom-client';
import { APIClient } from '../generated/apiClient';

// Create a hook for the API client
export const useAiClient = makeUseApiClient(APIClient);

// Define a component that uses the API client
export const SomeComponent = () => {
  // Get the API client
  const aiClient = useAiClient();

  // Return a div that creates a Todo when clicked
  return <div onClick={() => aiClient.Todo.create('text')}>Click me</div>;
  // ...
};

Reading Atoms in the frontend

Atoms can be subscribed to, this way all information will always be in sync with the backend automatically.

###creating a subscription client

import { makeUseAtom } from '@feinarbyte/atom-client';
import { atomDataIndex } from '../generated/atomdataindex';
import { AIAtoms } from '../generated/types';
export const useAiAtom = makeUseAtom<AIAtoms, atomDataIndex>();

using the subscription client

import { useAiAtom } from './useAiAtom';

// Define a functional component
export const SomeComponent = () => {
  // Use the atom client to subscribe to the Tag atom
  const tagAtom = useAiAtom(AIAtoms.Tag);

  // Use the atom client to subscribe to the Tag atom with a specific context
  const tagAtom = useAiAtom(AIAtoms.Tag, {[AiContext.Tag]: tagId});

  // Use the atom client to subscribe to the Tag atom and extract the id
  // If the tag is not found, it will return null
  const tag = useAiAtom(AIAtoms.Tag, (tag) => tag.id) ?? null;
  ....
8.4.0

4 months ago

8.1.0

7 months ago

8.1.1

7 months ago

8.3.2

7 months ago

8.3.1

7 months ago

8.2.0

7 months ago

8.3.0

7 months ago

6.8.0

10 months ago

6.9.0

10 months ago

6.9.1

10 months ago

7.0.0

8 months ago

7.0.2

8 months ago

7.0.1

8 months ago

6.10.0

9 months ago

8.0.0

8 months ago

6.5.0

1 year ago

6.6.1

1 year ago

6.6.0

1 year ago

6.6.3

1 year ago

6.6.2

1 year ago

6.6.4

1 year ago

6.7.0

12 months ago

5.2.2

1 year ago

5.2.1

1 year ago

5.2.0

1 year ago

6.0.1

1 year ago

6.0.0

1 year ago

6.0.2

1 year ago

5.3.1

1 year ago

5.3.0

1 year ago

6.1.0

1 year ago

5.4.5

1 year ago

5.4.4

1 year ago

5.4.3

1 year ago

5.4.2

1 year ago

5.4.1

1 year ago

5.4.0

1 year ago

6.2.0

1 year ago

6.0.0-0

1 year ago

6.3.4

1 year ago

6.3.3

1 year ago

6.3.6

1 year ago

6.3.5

1 year ago

5.4.3-1

1 year ago

5.4.3-0

1 year ago

6.3.0

1 year ago

6.3.2

1 year ago

6.3.1

1 year ago

6.4.3

1 year ago

6.4.2

1 year ago

6.4.4

1 year ago

6.4.1

1 year ago

6.4.0

1 year ago

5.1.0

1 year ago

4.9.0

1 year ago

5.0.0

1 year ago

4.8.1

1 year ago

4.8.0

1 year ago

4.8.2

1 year ago

4.7.1

1 year ago

4.4.1

1 year ago

4.4.0

1 year ago

4.4.2

1 year ago

4.3.2

1 year ago

4.3.1

1 year ago

4.7.0

1 year ago

4.6.1

1 year ago

4.6.0

1 year ago

4.5.0

1 year ago

4.3.0

1 year ago

4.2.1

1 year ago

4.2.0

1 year ago

4.1.3

1 year ago

1.2.0

2 years ago

1.14.0

2 years ago

1.18.1

2 years ago

1.18.0

2 years ago

2.27.1

1 year ago

1.6.0

2 years ago

2.23.1

1 year ago

2.27.0

1 year ago

2.11.0

2 years ago

2.4.1

2 years ago

2.4.0

2 years ago

2.8.1

2 years ago

2.8.0

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

2.19.0

1 year ago

2.19.1

1 year ago

2.9.1

2 years ago

2.15.0

2 years ago

2.15.1

2 years ago

2.22.1

1 year ago

2.22.0

1 year ago

4.0.1

1 year ago

4.0.0

1 year ago

4.0.2

1 year ago

1.15.0

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.19.0

2 years ago

1.15.2

2 years ago

1.15.1

2 years ago

1.9.1

2 years ago

1.9.0

2 years ago

1.5.1

2 years ago

2.22.2

1 year ago

1.5.0

2 years ago

2.26.0

1 year ago

2.10.1

2 years ago

2.3.0

2 years ago

2.10.0

2 years ago

2.3.1

2 years ago

2.7.0

2 years ago

3.1.0

1 year ago

2.18.3

1 year ago

2.18.1

1 year ago

2.18.2

1 year ago

2.14.3

2 years ago

2.18.0

1 year ago

2.14.1

2 years ago

2.14.2

2 years ago

2.14.0

2 years ago

2.21.0

1 year ago

0.22.1

2 years ago

1.10.1

2 years ago

1.10.0

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

1.12.0

2 years ago

1.16.1

2 years ago

1.16.0

2 years ago

1.8.0

2 years ago

2.25.0

1 year ago

1.4.0

2 years ago

1.0.4

2 years ago

2.25.1

1 year ago

1.0.3

2 years ago

2.2.0

2 years ago

2.6.0

2 years ago

3.0.3

1 year ago

3.0.2

1 year ago

3.0.1

1 year ago

2.17.0

1 year ago

2.17.1

1 year ago

3.0.0

1 year ago

2.13.0

2 years ago

2.20.0

1 year ago

1.11.0

2 years ago

1.13.2

2 years ago

1.13.1

2 years ago

1.13.0

2 years ago

1.17.0

2 years ago

1.13.3

2 years ago

2.28.0

1 year ago

1.7.0

2 years ago

2.24.1

1 year ago

2.24.0

1 year ago

1.3.1

2 years ago

1.3.0

2 years ago

2.12.0

2 years ago

2.5.0

2 years ago

2.5.1

2 years ago

2.9.0

2 years ago

2.1.0

2 years ago

2.16.1

2 years ago

2.16.2

2 years ago

2.16.0

2 years ago

2.23.0

1 year ago

4.1.0

1 year ago

4.1.2

1 year ago

4.1.1

1 year ago

0.22.0

2 years ago

0.21.3

2 years ago

0.21.2

2 years ago

0.21.1

2 years ago

0.21.0

2 years ago

0.20.4

2 years ago

0.20.3

2 years ago

0.20.2

2 years ago

0.20.1

2 years ago

0.20.0

2 years ago

0.19.11

2 years ago

0.19.10

2 years ago

0.19.9

2 years ago

0.19.8

2 years ago

0.19.7

2 years ago

0.19.6

2 years ago

0.19.5

2 years ago

0.19.4

2 years ago

0.19.3

2 years ago

0.19.2

2 years ago

0.19.1

2 years ago

0.19.0

2 years ago

0.18.0

2 years ago

0.17.4

2 years ago

0.17.3

2 years ago

0.17.2

2 years ago

0.17.1

2 years ago

0.17.0

2 years ago

0.16.2

2 years ago

0.16.1

2 years ago

0.16.0

2 years ago

0.15.0

2 years ago

0.14.1

2 years ago

0.14.0

2 years ago

0.13.2

2 years ago

0.13.1

2 years ago

0.13.0

2 years ago

0.12.1

2 years ago

0.12.0

2 years ago

0.11.2

2 years ago

0.11.1

2 years ago

0.11.0

2 years ago

0.10.2

2 years ago

0.10.1

2 years ago

0.10.0

2 years ago

0.9.1

2 years ago

0.9.0

2 years ago

0.8.1

2 years ago

0.8.0

2 years ago

0.7.4

2 years ago

0.7.3

2 years ago

0.7.2

2 years ago

0.7.1

2 years ago

0.7.0

2 years ago

0.6.0

2 years ago

0.5.2

2 years ago

0.5.1

2 years ago

0.5.0

2 years ago

0.4.2

2 years ago

0.4.1

2 years ago

0.4.0

2 years ago

0.3.4

2 years ago

0.3.3

2 years ago

0.3.2

2 years ago

0.3.1

2 years ago

0.3.0

2 years ago

0.2.3

2 years ago

0.2.2

2 years ago

0.2.1

2 years ago

0.1.5

2 years ago

0.1.4

2 years ago

0.1.3

2 years ago

0.1.1

2 years ago