Skip to content

Instantly share code, notes, and snippets.

@Aryk
Created April 22, 2017 06:22
Show Gist options
  • Save Aryk/860725e2306c5ef485e528d51b536efd to your computer and use it in GitHub Desktop.
Save Aryk/860725e2306c5ef485e528d51b536efd to your computer and use it in GitHub Desktop.
Redux Orm Type Definitions
// These are by no means complete. Please contribute so we can get it to a state where we can put it on DefinitelyTyped
declare module 'redux-orm' {
/**
* Handles the underlying data structure for a {@link Model} class.
*/
export class Backend {
/**
* Handles the underlying data structure for a {@link Model} class.
*/
constructor(userOpts: { idAttribute: string, arrName: string, mapName: string, withMutations: Boolean });
/**
* Returns a reference to the object at index `id`
* in state `branch`.
*
* @param {Object} branch - the state
* @param {Number} id - the id of the objec¡t to get
* @return {Object|undefined} A reference to the raw object in the state or
* `undefined` if not found.
*/
accessId(branch: Object, id: Number): (Object|undefined);
/**
* Returns a {@link ListIterator} instance for
* the list of objects in `branch`.
*
* @param {Object} branch - the model's state branch
* @return {ListIterator} An iterator that loops through the objects in `branch`
*/
iterator(branch: Object): utils.ListIterator;
/**
* Returns the default state for the data structure.
* @return {Object} The default state for this {@link Backend} instance's data structure
*/
getDefaultState(): Object;
/**
* Returns the data structure including a new object `entry`
* @param {Object} session - the current Session instance
* @param {Object} branch - the data structure state
* @param {Object} entry - the object to insert
* @return {Object} the data structure including `entry`.
*/
insert(session: Object, branch: Object, entry: Object): Object;
/**
* Returns the data structure with objects where id in `idArr`
* are merged with `mergeObj`.
*
* @param {Object} session - the current Session instance
* @param {Object} branch - the data structure state
* @param {Array} idArr - the id's of the objects to update
* @param {Object} mergeObj - The object to merge with objects
* where their id is in `idArr`.
* @return {Object} the data structure with objects with their id in `idArr` updated with `mergeObj`.
*/
update(session: Object, branch: Object, idArr: any[], mergeObj: Object): Object;
/**
* Returns the data structure without objects with their id included in `idsToDelete`.
* @param {Object} session - the current Session instance
* @param {Object} branch - the data structure state
* @param {Array} idsToDelete - the ids to delete from the data structure
* @return {Object} the data structure without ids in `idsToDelete`.
*/
delete(session: Object, branch: Object, idsToDelete: any[]): Object;
}
interface IStaticModel<M extends Model> extends QuerySetSharedMethods<M, QuerySet<M, QuerySet<M, any>>> {
propTypes: Object;
defaultProps: Object;
modelName: string;
fields: {[key: string]: any};
virtualFields: Object;
querySetClass: any; // not a QuerySet instance but the class itself.
reducer(action: any, modelClass: IStaticModel<any>, session: Session): void;
seeder(modelClass: any, session: Session): any;
_initFields(props: Object): any;
toString(): string;
options: any;
_getTableOpts(): any
_sessionData: any;
markAccessed(): any;
idAttribute: any;
connect(session: Session): void;
session: Session;
getQuerySet(): any;
invalidateClassCache(): any;
query: any;
create(props: Object): M;
withId(id: any): M;
hasId(id: any): Boolean;
_findDatabaseRows(Object): any;
get(lookupObj: Object): Model;
}
/**
* The heart of an ORM, the data model.
* The static class methods manages the updates
* passed to this. The class itself is connected to a seedSession,
* and because of this you can only have a single seedSession at a time
* for a {@link Model} class.
*
* An instance of {@link Model} represents an object in the database.
*
* To create data models in your orm, subclass {@link Model}. To define
* information about the data model, override static class methods. Define instance
* logic by defining prototype methods (without `static` keyword).
*/
// Aryk: Recent as of 0.9 RC1
export class Model {
/**
* Static variable modelName.
*/
static propTypes: Object;
/**
* Static variable modelName.
*/
static defaultProps: Object;
/**
* Static variable modelName.
*/
static modelName: string;
/**
* Static variable fields.
*/
static fields: Object;
/**
* Static variable virtualFields.
*/
static virtualFields: Object;
/**
* Static variable querySetClass.
*/
static querySetClass: any; // not a QuerySet instance but the class itself.
/**
* The default reducer implementation.
* If the user doesn't define a reducer, this is used.
*
* Passed through 'any' for model because can't seem to figure out how to pass through a model class.
*
* @param {Object} action - the dispatched action
* @param {Model} modelClass - the concrete model class being used
* @param {Session} session - the current {@link Session} instance
* @return {Object} the next state for the Model
*/
static reducer(action: any, modelClass: any, session: Session): void;
/**
* The default seeder implementation.
*
* Passed through 'any' for model because can't seem to figure out how to pass through a model class.
*
* Gets used when state is undefined on the reducer.
* @param {Model} modelClass - the concrete model class being used
* @param {Session} session - the current {@link Session} instance
*/
static seeder(modelClass: any, session: Session): any;
/**
* The heart of an ORM, the data model.
* The static class methods manages the updates
* passed to this. The class itself is connected to a seedSession,
* and because of this you can only have a single seedSession at a time
* for a {@link Model} class.
*
* An instance of {@link Model} represents an object in the database.
*
* To create data models in your orm, subclass {@link Model}. To define
* information about the data model, override static class methods. Define instance
* logic by defining prototype methods (without `static` keyword).
*/
constructor(props: Object);
static _initFields(props: Object): any;
/**
* Returns a string representation of the {@link Model} instance.
*
* @return {string} A string representation of this {@link Model} instance.
*/
static toString(): string;
static options: any;
static _getTableOpts(): any;
static _sessionData: any;
static markAccessed(): any;
/**
* Returns the id attribute of this {@link Model}.
*
* @return {string} The id attribute of this {@link Model}.
*/
static idAttribute: any;
/**
* Connect the model class to a {@link Session}.
*
* @private
* @param {Session} session - The seedSession to connect to.
*/
static connect(session: Session): void;
/**
* Get the current {@link Session} instance.
*
* @private
* @return {Session} The current {@link Session} instance.
*/
static session: Session;
static getQuerySet(): any;
static invalidateClassCache(): any;
static query: any;
/**
* Records the addition of a new {@link Model} instance and returns it.
*
* @param {props} props - the new {@link Model}'s properties.
* @return {Model} a new {@link Model} instance.
*/
static create(props: Object): Model;
/**
* Returns a {@link Model} instance for the object with id `id`.
* This throws if the `id` doesn't exist. Use {@link Model#hasId}
* to check for existence first if you're not certain.
*
* @param {*} id - the `id` of the object to get
* @throws If object with id `id` doesn't exist
* @return {Model} {@link Model} instance with id `id`
*/
static withId(id: any): any;
/**
* Returns a boolean indicating if an entity with the id `id` exists
* in the state.
*
* @param {*} id - a value corresponding to the id attribute of the {@link Model} class.
* @return {Boolean} a boolean indicating if entity with `id` exists in the state
*/
static hasId(id: any): Boolean;
static _findDatabaseRows(Object): any;
/**
* Gets the {@link Model} instance that matches properties in `lookupObj`.
* Throws an error if {@link Model} is not found, or multiple records match
* the properties.
*
* @param {Object} lookupObj - the properties used to match a single entity.
* @return {Model} a {@link Model} instance that matches `lookupObj` properties.
*/
static get(lookupObj: Object): Model;
/**
* Gets the {@link Model} class or subclass constructor (the class that
* instantiated this instance).
*
* @return {Model} The {@link Model} class or subclass constructor used to instantiate
* this instance.
*/
public getClass(): IStaticModel<Model>;
/**
* Gets the id value of the current instance by looking up the id attribute.
* @return {*} The id value of the current instance.
*/
getId(): any;
/**
* Returns a reference to the plain JS object in the store.
* Make sure to not mutate this.
*
* @return {Object} a reference to the plain JS object in the store
*/
ref: any;
/**
* Returns a string representation of the {@link Model} instance.
*
* @return {string} A string representation of this {@link Model} instance.
*/
toString(): string;
/**
* Returns a boolean indicating if `otherModel` equals this {@link Model} instance.
* Equality is determined by shallow comparing their attributes.
*
* @param {Model} otherModel - a {@link Model} instance to compare
* @return {Boolean} a boolean indicating if the {@link Model} instance's are equal.
*/
equals(otherModel: Model): Boolean;
/**
* Updates a property name to given value for this {@link Model} instance.
* The values are immediately committed to the database.
*
* @param {string} propertyName - name of the property to set
* @param {*} value - value assigned to the property
* @return {undefined}
*/
set(propertyName: string, value: any): undefined;
/**
* Assigns multiple fields and corresponding values to this {@link Model} instance.
* The updates are immediately committed to the database.
*
* @param {Object} userMergeObj - an object that will be merged with this instance.
* @return {undefined}
*/
update(userMergeObj: Object): undefined;
/**
* Updates {@link Model} instance attributes to reflect the
* database state in the current session.
* @return {undefined}
*/
refreshFromState(): any;
/**
* Deletes the record for this {@link Model} instance.
* You'll still be able to access fields and values on the instance.
*
* @return {undefined}
*/
delete(): undefined;
_onDelete(): any;
}
export class ORM {
/**
* Creates a new ORM instance.
*/
constructor(opts?: Object);
/**
* Registers a {@link Model} class to the ORM.
*
* If the model has declared any ManyToMany fields, their
* through models will be generated and registered with
* this call, unless a custom through model has been specified.
*
* @param {...Model} model - a {@link Model} class to register
* @return {undefined}
*/
register(...model: Array<typeof Model>);
registerManyToManyModelsFor(model: Model): void;
/**
* Gets a {@link Model} class by its name from the registry.
* @param {string} modelName - the name of the {@link Model} class to get
* @throws If {@link Model} class is not found.
* @return {Model} the {@link Model} class, if found
*/
get(modelName: string): IStaticModel<any>;
getModelClasses(): Model[];
_attachQuerySetMethods(model: Model): void;
isFieldInstalled(modelName: string, fieldName: string): boolean;
setFieldInstalled(modelName: string, fieldName: string): void;
_setupModelPrototypes(models: Model[]): void;
generateSchemaSpec(): Object;
getDatabase(): Object;
/**
* Returns the empty database state.
* @return {Object} the empty state
*/
getEmptyState(): Object;
/**
* Begins an immutable database seedSession.
*
* @param {Object} state - the state the database manages
* @return {Session} a new {@link Session} instance
*/
session(state: any): Session;
/**
* Begins a mutable database seedSession.
*
* @param {Object} state - the state the database manages
* @return {Session} a new {@link Session} instance
*/
mutableSession(state: any): Session;
}
class QuerySetSharedMethods<SubModel, SubQuerySet> {
/**
* Returns the number of model instances represented by the QuerySet.
*
* @return {number} length of the QuerySet
*/
count(): number;
/**
* Returns the {@link Model} instance at index `index` in the {@link QuerySet} instance if
* `withRefs` flag is set to `false`, or a reference to the plain JavaScript
* object in the model state if `true`.
*
* @param {number} index - index of the model instance to get
* @return {Model|Object} a {@link Model} instance or a plain JavaScript
* object at index `index` in the {@link QuerySet} instance
*/
at(index: number): (SubModel|Object);
/**
* Returns a new {@link QuerySet} instance with the same entities.
* @return {QuerySet} a new QuerySet with the same entities.
*/
all(): SubQuerySet;
/**
* Returns the {@link Model} instance at index `QuerySet.count() - 1`
* @return {Model}
*/
last(): SubModel;
/**
* Returns the {@link Model} instance at index 0 in the {@link QuerySet} instance.
* @return {Model}
*/
first(): SubModel;
/**
* Checks if the {@link QuerySet} instance has any entities.
*
* @return {Boolean} `true` if the {@link QuerySet} instance contains entities, else `false`.
*/
exists(): Boolean;
/**
* Returns a new {@link QuerySet} instance with entities that match properties in `lookupObj`.
*
* @param {Object} lookupObj - the properties to match objects with.
* @return {QuerySet} a new {@link QuerySet} instance with objects that passed the filter.
*/
filter(lookupObj: Object): SubQuerySet;
/**
* Returns a new {@link QuerySet} instance with entities that do not match properties in `lookupObj`.
*
* @param {Object} lookupObj - the properties to unmatch objects with.
* @return {QuerySet} a new {@link QuerySet} instance with objects that passed the filter.
*/
exclude(lookupObj: Object): SubQuerySet;
/**
* Returns a new {@link QuerySet} instance with entities ordered by `iteratees` in ascending
* order, unless otherwise specified. Delegates to `lodash.orderBy`.
*
* @param {string[]|Function[]} iteratees - an array where each item can be a string or a
* function. If a string is supplied, it should
* correspond to property on the entity that will
* determine the order. If a function is supplied,
* it should return the value to order by.
* @param {Boolean[]} [orders] - the sort orders of `iteratees`. If unspecified, all iteratees
* will be sorted in ascending order. `true` and `'asc'`
* correspond to ascending order, and `false` and `'desc`
* to descending order.
* @return {QuerySet} a new {@link QuerySet} with objects ordered by `iteratees`.
*/
orderBy(iteratees: (string[] | (() => any)[] | string), orders?: Boolean[]): SubQuerySet;
/**
* Records an update specified with `mergeObj` to all the objects
* in the {@link QuerySet} instance.
*
* @param {Object} mergeObj - an object to merge with all the objects in this
* queryset.
* @return {undefined}
*/
update(mergeObj: Object): undefined;
/**
* Records a deletion of all the objects in this {@link QuerySet} instance.
* @return {undefined}
*/
delete(): undefined;
}
/**
* A chainable class that keeps track of a list of objects and
*
* - returns a subset clone of itself with [filter]{@link QuerySet#filter} and [exclude]{@link QuerySet#exclude}
* - records updates to objects with [update]{@link QuerySet#update} and [delete]{@link QuerySet#delete}
*
* Aryk: Recent as of 0.9.1RC
*/
export class QuerySet<
SubModel extends Model,
SubQuerySet extends QuerySet<SubModel, SubQuerySet>
> extends QuerySetSharedMethods<SubModel, SubQuerySet> {
/**
* A chainable class that keeps track of a list of objects and
*
* - returns a subset clone of itself with [filter]{@link QuerySet#filter} and [exclude]{@link QuerySet#exclude}
* - records updates to objects with [update]{@link QuerySet#update} and [delete]{@link QuerySet#delete}
*
*/
constructor(modelClass: IStaticModel<SubModel>, idArr?: number[], opts?: Object);
// toString already exists on object;
_evaluate(): any;
_evaluated: boolean;
rows: SubModel[];
modelClass: any; // returns a class, not sure how to type it here.
/**
* Returns an array of the plain objects represented by the QuerySet.
* The plain objects are direct references to the store.
*
* @return {Object[]} references to the plain JS objects represented by
* the QuerySet
*/
toRefArray(): any[];
/**
* Returns an array of Model instances represented by the QuerySet.
* @return {Model[]} model instances represented by the QuerySet
*/
toModelArray(): SubModel[];
}
/**
* Schema's responsibility is tracking the set of {@link Model} classes used in the database.
* To include your model in that set, Schema offers {@link Schema#register} and a
* shortcut {@link Schema#define} methods.
*
* Schema also handles starting a Session with {@link Schema#from}.
*/
export class Schema {
/**
* Schema's responsibility is tracking the set of {@link Model} classes used in the database.
* To include your model in that set, Schema offers {@link Schema#register} and a
* shortcut {@link Schema#define} methods.
*
* Schema also handles starting a Session with {@link Schema#from}.
*/
constructor();
registry: Array<IStaticModel<any>>;
/**
* Defines a {@link Model} class with the provided options and registers
* it to the orm instance.
*
* Note that you can also define {@link Model} classes by yourself
* with ES6 classes.
*
* @param {string} modelName - the name of the {@link Model} class
* @param {Object} [relatedFields] - a dictionary of `fieldName: fieldInstance`
* @param {Function} [reducer] - the reducer function to use for this model
* @param {Object} [backendOpts] - {@link Backend} options for this model.
* @return {Model} The defined model class.
*/
define(modelName: string, relatedFields?: Object, reducer?: (() => any), backendOpts?: Object): Model;
/**
* Registers a {@link Model} class to the orm.
*
* If the model has declared any ManyToMany fields, their
* through models will be generated and registered with
* this call.
*
* @param {...Model} model - a {@link Model} class to register
* @return {undefined}
*/
register(model: IStaticModel<any>): undefined;
/**
* Gets a {@link Model} class by its name from the registry.
* @param {string} modelName - the name of the {@link Model} class to get
* @throws If {@link Model} class is not found.
* @return {Model} the {@link Model} class, if found
*/
get(modelName: string): Model;
getModelClasses(): Array<IStaticModel<any>>;
isFieldInstalled(modelName, fieldName): boolean;
setFieldInstalled(modelName, fieldName);
/**
* Begins an immutable database seedSession.
*
* @param {Object} state - the state the database manages
* @param {Object} [action] - the dispatched action object
* @return {Session} a new {@link Session} instance
*/
from(state: Object, action?: Object): Session;
/**
* Begins a mutable database seedSession.
*
* @param {Object} state - the state the database manages
* @param {Object} [action] - the dispatched action object
* @return {Session} a new {@link Session} instance
*/
withMutations(state: Object, action?: Object): Session;
/**
* Returns a reducer function you can plug into your own
* reducer. One way to do that is to declare your root reducer:
*
* ```javascript
* function rootReducer(state, action) {
* return {
* entities: orm.reducer(),
* // Any other reducers you use.
* }
* }
* ```
*
* @return {Function} a reducer function that creates a new {@link Session} on
* each action dispatch.
*/
reducer(): (() => any);
}
/**
* Session handles a single
* action dispatch.
*/
export class Session {
/**
* Session handles a single
* action dispatch.
*/
constructor(schema: Schema, state: Object, action: Object, withMutations: Boolean);
public schema: Schema;
public db;
public initialState;
public withMutations;
public batchToken;
public _accessedModels;
public modelData;
public models;
public sessionBoundModels;
public markAccessed(modelName: string): void;
/**
* Records an update to the seedSession.
*
* @private
* @param {Object} update - the update object. Must have keys
* `type`, `payload` and `meta`. `meta`
* must also include a `name` attribute
* that contains the model name.
*/
private addUpdate(update: Object): void;
/**
* Returns the current state for a model with name `modelName`.
*
* @private
* @param {string} modelName - the name of the model to get state for.
* @return {*} The state for model with name `modelName`.
*/
private getState(modelName: string): any;
/**
* Applies recorded updates and returns the next state.
* @param {Object} [opts] - Options object
* @param {Boolean} [opts.runReducers] - A boolean indicating if the user-defined
* model reducers should be run. If not specified,
* is set to `true` if an action object was specified
* on seedSession instantiation, otherwise `false`.
* @return {Object} The next state
*/
public state(opts?: { runReducers: Boolean }): Object;
/**
* Calls the user-defined reducers and returns the next state.
* If the seedSession uses mutations, just returns the state.
* Delegates to {@link Session#getNextState}
*
* @return {Object} the next state
*/
public reduce(): Object;
}
/**
* Handles a single unit of work on the database backend.
*/
export class Transaction {
/**
* Handles a single unit of work on the database backend.
*/
constructor();
}
/**
* A memoizer to use with redux-orm
* selectors. When the memoized function is first run,
* the memoizer will remember the models that are accessed
* during that function run.
*
* On subsequent runs, the memoizer will check if those
* models' states have changed compared to the previous run.
*
* Memoization algorithm operates like this:
*
* 1. Has the selector been run before? If not, go to 5.
*
* 2. If the selector has other input selectors in addition to the
* ORM state selector, check their results for equality with the previous results.
* If they aren't equal, go to 5.
*
* 3. Is the ORM state referentially equal to the previous ORM state the selector
* was called with? If yes, return the previous result.
*
* 4. Check which Model's states the selector has accessed on previous runs.
* Check for equality with each of those states versus their states in the
* previous ORM state. If all of them are equal, return the previous result.
*
* 5. Run the selector. Check the Session object used by the selector for
* which Model's states were accessed, and merge them with the previously
* saved information about accessed models (if-else branching can change
* which models are accessed on different inputs). Save the ORM state and
* other arguments the selector was called with, overriding previously
* saved values. Save the selector result. Return the selector result.
*
* @private
* @param {Function} func - function to memoize
* @param {Function} equalityCheck - equality check function to use with normal
* selector args
* @param {Schema} modelSchema - a redux-orm Schema instance
* @return {Function} `func` memoized.
*/
export function memoize(func: (() => any), equalityCheck: (() => any), modelSchema: Schema): (() => any);
/**
* @module utils
*/
namespace utils {
/**
* A simple ListIterator implementation.
*/
class ListIterator {
/**
* A simple ListIterator implementation.
*/
constructor(list: any[], idx?: Number, getValue?: (() => any));
/**
* The default implementation for the `getValue` function.
*
* @param {Number} idx - the current iterator index
* @param {Array} list - the list being iterated
* @return {*} - the value at index `idx` in `list`.
*/
getValue(idx: Number, list: any[]): any;
/**
* Returns the next element from the iterator instance.
* Always returns an Object with keys `value` and `done`.
* If the returned element is the last element being iterated,
* `done` will equal `true`, otherwise `false`. `value` holds
* the value returned by `getValue`.
*
* @return {Object|undefined} Object with keys `value` and `done`, or
* `undefined` if the list index is out of bounds.
*/
next(): (Object|undefined);
}
/**
* Checks if the properties in `lookupObj` match
* the corresponding properties in `entity`.
*
* @private
* @param {Object} lookupObj - properties to match against
* @param {Object} entity - object to match
* @return {Boolean} Returns `true` if the property names in
* `lookupObj` have the same values in `lookupObj`
* and `entity`, `false` if not.
*/
function match(lookupObj: Object, entity: Object): Boolean;
/**
* Returns the branch name for a many-to-many relation.
* The name is the combination of the model name and the field name the relation
* was declared. The field name's first letter is capitalized.
*
* Example: model `Author` has a many-to-many relation to the model `Book`, defined
* in the `Author` field `books`. The many-to-many branch name will be `AuthorBooks`.
*
* @private
* @param {string} declarationModelName - the name of the model the many-to-many relation was declared on
* @param {string} fieldName - the field name where the many-to-many relation was declared on
* @return {string} The branch name for the many-to-many relation.
*/
function m2mName(declarationModelName: string, fieldName: string): string;
/**
* Returns the fieldname that saves a foreign key to the
* model id where the many-to-many relation was declared.
*
* Example: `Author` => `fromAuthorId`
*
* @private
* @param {string} declarationModelName - the name of the model where the relation was declared
* @return {string} the field name in the through model for `declarationModelName`'s foreign key.
*/
function m2mFromFieldName(declarationModelName: string): string;
/**
* Returns the fieldname that saves a foreign key in a many-to-many through model to the
* model where the many-to-many relation was declared.
*
* Example: `Book` => `toBookId`
*
* @private
* @param {string} otherModelName - the name of the model that was the target of the many-to-many
* declaration.
* @return {string} the field name in the through model for `otherModelName`'s foreign key..
*/
function m2mToFieldName(otherModelName: string): string;
/**
* Normalizes `entity` to an id, where `entity` can be an id
* or a Model instance.
*
* @private
* @param {*} entity - either a Model instance or an id value
* @return {*} the id value of `entity`
*/
function normalizeEntity(entity: any): any;
}
export function createSelector(orm: ORM, ...args: any[]): any
/**
* @module fields
*/
/**
* Defines a value attribute on the model.
* You need to define this for each non-foreign key you wish to use.
* You can use the optional `getDefault` parameter to fill in unpassed values
* to {@link Model#create}, such as for generating ID's with UUID:
*
* ```javascript
* import getUUID from 'your-uuid-package-of-choice';
*
* fields = {
* id: attr({ getDefault: () => getUUID() }),
* title: attr(),
* }
* ```
*
* @param {Object} [opts]
* @param {Function} [opts.getDefault] - if you give a function here, it's return
* value from calling with zero arguments will
* be used as the value when creating a new Model
* instance with {@link Model#create} if the field
* value is not passed.
* @return {Attribute}
*/
export function attr(opts?: {getDefault: any | (() => any)}): void;
/**
* Defines a foreign key on a model, which points
* to a single entity on another model.
*
* You can pass arguments as either a single object,
* or two arguments.
*
* If you pass two arguments, the first one is the name
* of the Model the foreign key is pointing to, and
* the second one is an optional related name, which will
* be used to access the Model the foreign key
* is being defined from, from the target Model.
*
* If the related name is not passed, it will be set as
* `${toModelName}Set`.
*
* If you pass an object to `fk`, it has to be in the form
*
* ```javascript
* fields = {
* author: fk({ to: 'Author', relatedName: 'books' })
* }
* ```
*
* Which is equal to
*
* ```javascript
* fields = {
* author: fk('Author', 'books'),
* }
* ```
*
* @param {string|boolean} toModelNameOrObj - the `modelName` property of
* the Model that is the target of the
* foreign key, or an object with properties
* `to` and optionally `relatedName`.
* @param {string} [relatedName] - if you didn't pass an object as the first argument,
* this is the property name that will be used to
* access a QuerySet the foreign key is defined from,
* from the target model.
* @return {ForeignKey}
*/
export function fk(
toModelNameOrObj: string | {to: string, relatedName?: string},
relatedName?: string,
): any;
/**
* Defines a many-to-many relationship between
* this (source) and another (target) model.
*
* The relationship is modeled with an extra model called the through model.
* The through model has foreign keys to both the source and target models.
*
* You can define your own through model if you want to associate more information
* to the relationship. A custom through model must have at least two foreign keys,
* one pointing to the source Model, and one pointing to the target Model.
*
* If you have more than one foreign key pointing to a source or target Model in the
* through Model, you must pass the option `throughFields`, which is an array of two
* strings, where the strings are the field names that identify the foreign keys to
* be used for the many-to-many relationship. Redux-ORM will figure out which field name
* points to which model by checking the through Model definition.
*
* Unlike `fk`, this function accepts only an object argument.
*
* ```javascript
* class Authorship extends Model {}
* Authorship.modelName = 'Authorship';
* Authorship.fields = {
* author: fk('Author', 'authorships'),
* book: fk('Book', 'authorships'),
* };
*
* class Author extends Model {}
* Author.modelName = 'Author';
* Author.fields = {
* books: many({
* to: 'Book',
* relatedName: 'authors',
* through: 'Authorship',
*
* // this is optional, since Redux-ORM can figure
* // out the through fields itself as there aren't
* // multiple foreign keys pointing to the same models.
* throughFields: ['author', 'book'],
* })
* };
*
* class Book extends Model {}
* Book.modelName = 'Book';
* ```
*
* You should only define the many-to-many relationship on one side. In the
* above case of Authors to Books through Authorships, the relationship is
* defined only on the Author model.
*
* @param {Object} options - options
* @param {string} options.to - the `modelName` attribute of the target Model.
* @param {string} [options.through] - the `modelName` attribute of the through Model which
* must declare at least one foreign key to both source and
* target Models. If not supplied, Redux-Orm will autogenerate
* one.
* @param {string[]} [options.throughFields] - this must be supplied only when a custom through
* Model has more than one foreign key pointing to
* either the source or target mode. In this case
* Redux-ORM can't figure out the correct fields for
* you, you must provide them. The supplied array should
* have two elements that are the field names for the
* through fields you want to declare the many-to-many
* relationship with. The order doesn't matter;
* Redux-ORM will figure out which field points to
* the source Model and which to the target Model.
* @param {string} [options.relatedName] - the attribute used to access a QuerySet
* of source Models from target Model.
* @return {ManyToMany}
*/
export function many(options: {
to: string,
through?: string,
throughFields: Array<string>,
relatedName: string,
}): any;
/**
* Defines a one-to-one relationship. In database terms, this is a foreign key with the
* added restriction that only one entity can point to single target entity.
*
* The arguments are the same as with `fk`. If `relatedName` is not supplied,
* the source model name in lowercase will be used. Note that with the one-to-one
* relationship, the `relatedName` should be in singular, not plural.
* @param {string|boolean} toModelNameOrObj - the `modelName` property of
* the Model that is the target of the
* foreign key, or an object with properties
* `to` and optionally `relatedName`.
* @param {string} [relatedName] - if you didn't pass an object as the first argument,
* this is the property name that will be used to
* access a Model the foreign key is defined from,
* from the target Model.
* @return {OneToOne}
*/
export function oneToOne(
toModelNameOrObj: string | {to: string, relatedName?: string},
relatedName?: string,
): any;
}
@jakelazaroff
Copy link

Any chance of making this a repo rather than a gist? I'd like to contribute!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment