Skip to content

Commit

Permalink
docs(models): add more documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Lodin committed Jul 15, 2024
1 parent 67c8d8c commit 153ed63
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 10 deletions.
17 changes: 8 additions & 9 deletions packages/ts/models/src/builders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import {

const { create, defineProperty } = Object;

/**
* The options for creating the model property.
*/
export type ModelBuilderPropertyOptions = Readonly<{
meta?: ModelMetadata;
}>;
Expand Down Expand Up @@ -49,12 +52,6 @@ export type Flags = {
* @typeParam EX - The extra properties of the model.
* @typeParam F - The flags for the model constructor that allow to determine
* specific characteristics of the model.
*
* @param base - The base model to extend.
* @param defaultValueProvider - The function that provides the default value
* for the model.
*
* @internal
*/
export class CoreModelBuilder<
V,
Expand All @@ -63,6 +60,11 @@ export class CoreModelBuilder<
> {
protected readonly [$model]: Model<V, EX>;

/**
* @param base - The base model to extend.
* @param defaultValueProvider - The function that provides the default value
* for the model.
*/
constructor(base: Model, defaultValueProvider?: (model: Model<V, EX>) => V) {
this[$model] = create(base);

Expand Down Expand Up @@ -163,9 +165,6 @@ const propertyRegistry = new WeakMap<Model, Record<string, Model>>();
* @typeParam EX - The extra properties of the model.
* @typeParam F - The flags for the model constructor that allow to determine
* specific characteristics of the model.
*
*
* @internal
*/
export class ObjectModelBuilder<
V extends AnyObject,
Expand Down
24 changes: 24 additions & 0 deletions packages/ts/models/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,33 @@ import type { EmptyObject } from 'type-fest';
import { CoreModelBuilder } from './builders.js';
import { $enum, $itemModel, type $members, type AnyObject, type Enum, Model, type Value } from './model.js';

/**
* The model of a primitive value, like `string`, `number` or `boolean`.
*/
export type PrimitiveModel<V = unknown> = Model<V>;
export const PrimitiveModel = new CoreModelBuilder(Model, (): unknown => undefined).name('primitive').build();

/**
* The model of a string value.
*/
export type StringModel = PrimitiveModel<string>;
export const StringModel = new CoreModelBuilder(PrimitiveModel, () => '').name('string').build();

/**
* The model of a number value.
*/
export type NumberModel = PrimitiveModel<number>;
export const NumberModel = new CoreModelBuilder(PrimitiveModel, () => 0).name('number').build();

/**
* The model of a boolean value.
*/
export type BooleanModel = PrimitiveModel<boolean>;
export const BooleanModel = new CoreModelBuilder(PrimitiveModel, () => false).name('boolean').build();

/**
* The model of an array data.
*/
export type ArrayModel<M extends Model = Model> = Model<
Array<Value<M>>,
Readonly<{
Expand All @@ -26,10 +41,16 @@ export const ArrayModel = new CoreModelBuilder(Model, (): unknown[] => [])
.define($itemModel, { value: Model })
.build();

/**
* The model of an object data.
*/
export type ObjectModel<V, EX extends AnyObject = EmptyObject, R extends keyof any = never> = Model<V, EX, R>;

export const ObjectModel = new CoreModelBuilder(Model, (): AnyObject => ({})).name('Object').build();

/**
* The model of an enum data.
*/
export type EnumModel<T extends typeof Enum> = Model<
T[keyof T],
Readonly<{
Expand All @@ -44,4 +65,7 @@ export const EnumModel = new CoreModelBuilder<(typeof Enum)[keyof typeof Enum]>(
.defaultValueProvider((self) => Object.values(self[$enum])[0])
.build();

/**
* The model of a union data.
*/
export type UnionModel<MM extends Model[]> = Model<Value<MM[number]>, Readonly<{ [$members]: MM }>>;
12 changes: 12 additions & 0 deletions packages/ts/models/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {

export * from './model.js';
export * from './core.js';
export type * from './builders.js';

const { defineProperty } = Object;

Expand All @@ -41,7 +42,18 @@ function getRawValue<T>(model: Model<T>): T | typeof nothing {
return (model[$owner] as Target<T>).value;
}

/**
* The utility object that provides methods to create and manipulate models.
*/
const m = {
/**
* Attaches the given model to the target.
*
* @param model - The model to attach.
* @param target - The target to attach the model to. It could be a Binder
* instance, a Signal, or another object. However, it could never be another
* model.
*/
attach<M extends Model>(model: M, target: Target<Value<M>>): M {
const _model = new CoreModelBuilder<Value<M>, Extensions<M>, { named: false; selfRefKeys: References<M> }>(model)
.name(`@${model[$name]}`)
Expand Down
50 changes: 49 additions & 1 deletion packages/ts/models/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,67 @@ export declare enum Enum {}

export type AnyObject = Readonly<Record<never, never>>; // {}

/* eslint-disable tsdoc/syntax */
/**
* The symbol that represents the {@link Model[$key]} property.
*/
export const $key = Symbol('key');

/**
* The symbol that represents the {@link Model[$name]} property.
*/
export const $name = Symbol('name');

/**
* The symbol that represents the {@link Model[$owner]} property.
*/
export const $owner = Symbol('owner');

/**
* The symbol that represents the {@link Model[$meta]} property.
*/
export const $meta = Symbol('meta');

/**
* The symbol that represents the {@link Model[$optional]} property.
*/
export const $optional = Symbol('optional');

/**
* The symbol that represents the {@link Model[$value]} property.
*/
export const $defaultValue = Symbol('value');

export const $enum = Symbol('enum');
/**
* The symbol that represents the {@link EnumModel[$enumerate]} property.
*/
export const $enum = Symbol('enumerate');

/**
* The symbol that represents the {@link UnionModel[$members]} property.
*/
export const $members = Symbol('members');

/**
* The symbol that represents the {@link ArrayModel[$itemModel]} property.
*/
export const $itemModel = Symbol('itemModel');

/* eslint-enable tsdoc/syntax */

/**
* Extracts the value type the model represents.
*/
export type Value<M extends Model> = M extends Model<infer T> ? T : never;

/**
* Extracts the list of extra properties of the model.
*/
export type Extensions<M extends Model> = M extends Model<unknown, infer EX> ? EX : EmptyObject;

/**
* Extracts the list of self-referencing properties of the model.
*/
export type References<M extends Model> = M extends Model<unknown, AnyObject, infer R> ? R : never;

/**
Expand Down

0 comments on commit 153ed63

Please sign in to comment.