Skip to main content

Configuring models

What you'll learn
  • Configuring a model through its factory or with a custom factory
  • Learning each available configuration option goal and usage

How to configure a model​

You may configure your model when creating them through your factory makeModel or when defining a custom factory such as described in the model composition guide.

Inside a model creation:

post.js
import { makeModel } from 'foscia/core';

class Post extends makeModel(
{
type: 'posts',
/* ...configuration */
},
{
/* ...definition */
},
) {}

Common to multiple models through a custom model factory:

makeModel.js
import { attr, makeModelFactory, toDate } from 'foscia/core';

export default makeModelFactory(
{
/* ...definition */
},
{
/* ...configuration */
},
);

Common​

Record type​

When using the model factory makeModel, you have probably seen that the first argument of the function is a string. This is the type of the current model.

It may be used for different purpose depending on the context:

  • Concatenate in a URL to target an API specific resource
  • Identify a record from an API/data source serialized data
  • Etc.

To define it, you should follow your data source convention. As an example, in a JSON:API the resource types are defined in plural kebab case, such as blog-posts or comments.

You may define the type as the only configuration of the model or as a configuration property (if you want to define other properties):

post.js
import { makeModel } from 'foscia/core';

class Post extends makeModel('posts', {
/* ...definition */
}) {}
// OR
class Post extends makeModel(
{ type: 'posts' },
{
/* ...definition */
},
) {}

Record path​

The path is used to query the model. It defaults to the model's type.

In an HTTP API, it is used as the endpoint. In a SQL database, it would be the table.

post.js
import { makeModel } from 'foscia/core';

class Post extends makeModel(
{
type: 'posts',
path: 'blog-posts',
},
{
/* definition */
},
) {}

Comparator and cloner​

You may have noticed that Foscia provide some model history features. Those allow you to know which parts of a model instance changed since its retrieval from the data source or interact with those changes, through some utilities functions: changed, reset, and syncOriginal.

Currently, Foscia won't clone any value when syncing the instance values (on save, etc.) and will do a strict equal comparison to known if the value changed.

The following model configuration is equivalent to the default behavior of Foscia:

post.js
import { makeModel } from 'foscia/core';

class Post extends makeModel(
{
type: 'posts',
compareValue: (newValue, prevValue) => nextValue === prevValue,
cloneValue: (value) => value,
},
{
/* definition */
},
) {}

You may change those two functions to really clone values when syncing the instance state. Keep in mind that:

  • Values might be any value your instance could contain, including complex object and even other model instance
  • Cloned values might be restored through reset utility
  • Making a real clone of a value without updating the comparator will break the history because of its default behavior

Type guesser​

To avoid defining types on all your relations even when necessary (for example in some cases with REST implementation), you may configure a type guesser on your models.

Here is an example of a type guesser using hypothetical toKebabCase and pluralize functions. For example, if a Comment model has a blogPost relation, this would guess the type to blog-posts;

post.js
import { makeModel, isManyRelationDef } from 'foscia/core';

class Post extends makeModel(
{
type: 'posts',
guessType: (def: ModelRelationRaw) =>
toKebabCase(isManyRelationDef(def) ? def.key : pluralize(def.key)),
},
{
/* definition */
},
) {}

HTTP​

The following configuration options are specific to HTTP models (JSON:API, JSON REST, etc.)

Base URL​

You may define a baseURL configuration option on your models. It will replace the default base URL define on the adapter.

post.js
import { makeModel } from 'foscia/core';

class Post extends makeModel(
{
type: 'posts',
baseURL: 'https://example.com/api/v2',
},
{
/* ...definition */
},
) {}