mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
Client lifecycle hooks (#7407)
* Add example client lifecycle hooks * AfterCreate, AfterDelete hooks
This commit is contained in:
@@ -12,7 +12,9 @@ import type CollectionsStore from "~/stores/CollectionsStore";
|
||||
import Document from "~/models/Document";
|
||||
import ParanoidModel from "~/models/base/ParanoidModel";
|
||||
import { client } from "~/utils/ApiClient";
|
||||
import Logger from "~/utils/Logger";
|
||||
import Field from "./decorators/Field";
|
||||
import { AfterUpdate } from "./decorators/Lifecycle";
|
||||
|
||||
export default class Collection extends ParanoidModel {
|
||||
static modelName = "Collection";
|
||||
@@ -324,4 +326,11 @@ export default class Collection extends ParanoidModel {
|
||||
format,
|
||||
includeAttachments,
|
||||
});
|
||||
|
||||
// hooks
|
||||
|
||||
@AfterUpdate
|
||||
static testing(model: Collection) {
|
||||
Logger.info("lifecycle", "AfterUpdate", { model });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { JSONObject } from "@shared/types";
|
||||
import type Store from "~/stores/base/Store";
|
||||
import Logger from "~/utils/Logger";
|
||||
import { getFieldsForModel } from "../decorators/Field";
|
||||
import { LifecycleManager } from "../decorators/Lifecycle";
|
||||
import { getRelationsForModelClass } from "../decorators/Relation";
|
||||
|
||||
export default abstract class Model {
|
||||
@@ -84,6 +85,7 @@ export default abstract class Model {
|
||||
params?: Record<string, any>,
|
||||
options?: Record<string, string | boolean | number | undefined>
|
||||
): Promise<Model> => {
|
||||
const isNew = this.isNew;
|
||||
this.isSaving = true;
|
||||
|
||||
try {
|
||||
@@ -92,6 +94,12 @@ export default abstract class Model {
|
||||
params = this.toAPI();
|
||||
}
|
||||
|
||||
if (isNew) {
|
||||
LifecycleManager.executeHooks(this.constructor, "beforeCreate", this);
|
||||
} else {
|
||||
LifecycleManager.executeHooks(this.constructor, "beforeUpdate", this);
|
||||
}
|
||||
|
||||
const model = await this.store.save(
|
||||
{
|
||||
...params,
|
||||
@@ -99,7 +107,7 @@ export default abstract class Model {
|
||||
},
|
||||
{
|
||||
...options,
|
||||
isNew: this.isNew,
|
||||
isNew,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -108,6 +116,12 @@ export default abstract class Model {
|
||||
|
||||
this.persistedAttributes = this.toAPI();
|
||||
|
||||
if (isNew) {
|
||||
LifecycleManager.executeHooks(this.constructor, "afterCreate", this);
|
||||
} else {
|
||||
LifecycleManager.executeHooks(this.constructor, "afterUpdate", this);
|
||||
}
|
||||
|
||||
return model;
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
@@ -138,7 +152,10 @@ export default abstract class Model {
|
||||
this.isSaving = true;
|
||||
|
||||
try {
|
||||
return await this.store.delete(this);
|
||||
LifecycleManager.executeHooks(this.constructor, "beforeDelete", this);
|
||||
const response = await this.store.delete(this);
|
||||
LifecycleManager.executeHooks(this.constructor, "afterDelete", this);
|
||||
return response;
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
export class LifecycleManager {
|
||||
private static hooks = new Map();
|
||||
|
||||
public static getHooks(target: any, lifecycle: string) {
|
||||
const key = `lifecycle:${lifecycle}`;
|
||||
const modelHooks = this.hooks.get(target.name);
|
||||
return modelHooks?.get(key) || [];
|
||||
}
|
||||
|
||||
public static executeHooks(target: any, lifecycle: string, ...args: any[]) {
|
||||
const hooks = this.getHooks(target, lifecycle);
|
||||
hooks.forEach((hook: keyof typeof target) => {
|
||||
target[hook](...args);
|
||||
});
|
||||
}
|
||||
|
||||
public static registerHook(
|
||||
target: any,
|
||||
propertyKey: string,
|
||||
lifecycle: string
|
||||
) {
|
||||
const key = `lifecycle:${lifecycle}`;
|
||||
let modelHooks = this.hooks.get(target.name);
|
||||
|
||||
if (!modelHooks) {
|
||||
modelHooks = new Map();
|
||||
this.hooks.set(target.name, modelHooks);
|
||||
}
|
||||
|
||||
let lifecycleHooks = modelHooks.get(key);
|
||||
if (!lifecycleHooks) {
|
||||
lifecycleHooks = [];
|
||||
modelHooks.set(key, lifecycleHooks);
|
||||
}
|
||||
|
||||
lifecycleHooks.push(propertyKey);
|
||||
}
|
||||
}
|
||||
|
||||
export function BeforeCreate(target: any, propertyKey: string) {
|
||||
LifecycleManager.registerHook(target, propertyKey, "beforeCreate");
|
||||
}
|
||||
|
||||
export function AfterCreate(target: any, propertyKey: string) {
|
||||
LifecycleManager.registerHook(target, propertyKey, "afterCreate");
|
||||
}
|
||||
|
||||
export function BeforeUpdate(target: any, propertyKey: string) {
|
||||
LifecycleManager.registerHook(target, propertyKey, "beforeUpdate");
|
||||
}
|
||||
|
||||
export function AfterUpdate(target: any, propertyKey: string) {
|
||||
LifecycleManager.registerHook(target, propertyKey, "afterUpdate");
|
||||
}
|
||||
|
||||
export function BeforeDelete(target: any, propertyKey: string) {
|
||||
LifecycleManager.registerHook(target, propertyKey, "beforeDelete");
|
||||
}
|
||||
|
||||
export function AfterDelete(target: any, propertyKey: string) {
|
||||
LifecycleManager.registerHook(target, propertyKey, "afterDelete");
|
||||
}
|
||||
Reference in New Issue
Block a user