1
0
mirror of https://github.com/flarum/core.git synced 2025-07-16 06:16:23 +02:00

feat: frontend Model extender (#3646)

* feat: reintroduce frontend extenders
* chore: used `Routes` extender in bundled extensions
* chore: used `PostTypes` extender in bundled extensions
* chore: `yarn format`
* feat: `Model` frontend extender
* chore: naming
* chore(review): attributes can be nullable or undefined
* chore(review): delay extender implementation
* chore(review): unnecessary check
* chore(review): stay consistent
* chore: merge conflicts
* chore: unused import
* chore: multiline extenders
* feat: add Store extender

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
This commit is contained in:
Sami Mazouz
2023-02-08 21:13:53 +01:00
committed by GitHub
parent f9a5d485c3
commit 47b670aa29
28 changed files with 220 additions and 67 deletions

View File

@ -83,9 +83,9 @@ export default class Store {
* The model registry. A map of resource types to the model class that
* should be used to represent resources of that type.
*/
models: Record<string, typeof Model>;
models: Record<string, { new (): Model }>;
constructor(models: Record<string, typeof Model>) {
constructor(models: Record<string, { new (): Model }>) {
this.models = models;
}

View File

@ -0,0 +1,42 @@
import IExtender, { IExtensionModule } from './IExtender';
import Application from '../Application';
import ActualModel from '../Model';
export default class Model implements IExtender {
private readonly model: { new (): ActualModel };
private callbacks: Array<() => void> = [];
public constructor(model: { new (): ActualModel }) {
this.model = model;
}
public attribute<T, O = unknown>(name: string, transform: ((attr: O) => T) | null = null): Model {
this.callbacks.push(() => {
this.model.prototype[name] = transform ? ActualModel.attribute<T, O>(name, transform) : ActualModel.attribute<T>(name);
});
return this;
}
public hasOne<M extends ActualModel>(name: string): Model {
this.callbacks.push(() => {
this.model.prototype[name] = ActualModel.hasOne<M>(name);
});
return this;
}
public hasMany<M extends ActualModel>(name: string): Model {
this.callbacks.push(() => {
this.model.prototype[name] = ActualModel.hasMany<M>(name);
});
return this;
}
extend(app: Application, extension: IExtensionModule): void {
for (const callback of this.callbacks) {
callback.call(this);
}
}
}

View File

@ -0,0 +1,23 @@
import Application from '../Application';
import IExtender, { IExtensionModule } from './IExtender';
import Model from '../Model';
export default class Store implements IExtender {
private readonly models: { [type: string]: { new (): Model } } = {};
public add(type: string, model: { new (): Model }): Store {
this.models[type] = model;
return this;
}
extend(app: Application, extension: IExtensionModule): void {
for (const type in this.models) {
if (app.store.models[type]) {
throw new Error(`The model type "${type}" has already been registered with the class "${app.store.models[type].name}".`);
}
app.store.models[type] = this.models[type];
}
}
}

View File

@ -1,7 +1,11 @@
import Model from './Model';
import PostTypes from './PostTypes';
import Routes from './Routes';
import Store from './Store';
export default {
Model,
PostTypes,
Routes,
Store,
};