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:
@ -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;
|
||||
}
|
||||
|
||||
|
42
framework/core/js/src/common/extenders/Model.ts
Normal file
42
framework/core/js/src/common/extenders/Model.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
23
framework/core/js/src/common/extenders/Store.ts
Normal file
23
framework/core/js/src/common/extenders/Store.ts
Normal 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];
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
};
|
||||
|
Reference in New Issue
Block a user