mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-15 20:17:22 +00:00
feat: add timestamps plugin to manage created_at and updated_at fields
Introduced a new timestamps plugin that allows the addition of `created_at` and `updated_at` fields to specified entities. Included tests to verify functionality, ensuring timestamps are correctly set on entity creation and updates. Updated the plugin index to export the new timestamps functionality.
This commit is contained in:
74
app/src/plugins/data/timestamp.plugin.spec.ts
Normal file
74
app/src/plugins/data/timestamp.plugin.spec.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
||||||
|
import { timestamps } from "./timestamps.plugin";
|
||||||
|
import { em, entity, text } from "bknd";
|
||||||
|
import { createApp } from "core/test/utils";
|
||||||
|
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
||||||
|
|
||||||
|
beforeAll(() => disableConsoleLog());
|
||||||
|
afterAll(enableConsoleLog);
|
||||||
|
|
||||||
|
describe("timestamps plugin", () => {
|
||||||
|
test("should ignore if no or invalid entities are provided", async () => {
|
||||||
|
const app = createApp({
|
||||||
|
options: {
|
||||||
|
plugins: [timestamps({ entities: [] })],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await app.build();
|
||||||
|
expect(app.em.entities.map((e) => e.name)).toEqual([]);
|
||||||
|
|
||||||
|
{
|
||||||
|
const app = createApp({
|
||||||
|
options: {
|
||||||
|
plugins: [timestamps({ entities: ["posts"] })],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await app.build();
|
||||||
|
expect(app.em.entities.map((e) => e.name)).toEqual([]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add timestamps to the specified entities", async () => {
|
||||||
|
const app = createApp({
|
||||||
|
config: {
|
||||||
|
data: em({
|
||||||
|
posts: entity("posts", {
|
||||||
|
title: text(),
|
||||||
|
}),
|
||||||
|
}).toJSON(),
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
plugins: [timestamps({ entities: ["posts", "invalid"] })],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await app.build();
|
||||||
|
expect(app.em.entities.map((e) => e.name)).toEqual(["posts"]);
|
||||||
|
expect(app.em.entity("posts")?.fields.map((f) => f.name)).toEqual([
|
||||||
|
"id",
|
||||||
|
"title",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
]);
|
||||||
|
|
||||||
|
// insert
|
||||||
|
const mutator = app.em.mutator(app.em.entity("posts"));
|
||||||
|
const { data } = await mutator.insertOne({ title: "Hello" });
|
||||||
|
expect(data.created_at).toBeDefined();
|
||||||
|
expect(data.updated_at).toBeDefined();
|
||||||
|
expect(data.created_at).toBeInstanceOf(Date);
|
||||||
|
expect(data.updated_at).toBeInstanceOf(Date);
|
||||||
|
const diff = data.created_at.getTime() - data.updated_at.getTime();
|
||||||
|
expect(diff).toBeLessThan(10);
|
||||||
|
expect(diff).toBeGreaterThan(-1);
|
||||||
|
|
||||||
|
// update (set updated_at to null, otherwise it's too fast to test)
|
||||||
|
await app.em.connection.kysely
|
||||||
|
.updateTable("posts")
|
||||||
|
.set({ updated_at: null })
|
||||||
|
.where("id", "=", data.id)
|
||||||
|
.execute();
|
||||||
|
const { data: updatedData } = await mutator.updateOne(data.id, { title: "Hello 2" });
|
||||||
|
expect(updatedData.updated_at).toBeDefined();
|
||||||
|
expect(updatedData.updated_at).toBeInstanceOf(Date);
|
||||||
|
});
|
||||||
|
});
|
||||||
86
app/src/plugins/data/timestamps.plugin.ts
Normal file
86
app/src/plugins/data/timestamps.plugin.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import { type App, type AppPlugin, em, entity, datetime, DatabaseEvents } from "bknd";
|
||||||
|
import { $console } from "bknd/utils";
|
||||||
|
|
||||||
|
export type TimestampsPluginOptions = {
|
||||||
|
entities: string[];
|
||||||
|
setUpdatedOnCreate?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This plugin adds `created_at` and `updated_at` fields to the specified entities.
|
||||||
|
* Add it to your plugins in `bknd.config.ts` like this:
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* export default {
|
||||||
|
* plugins: [timestamps({ entities: ["posts"] })],
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function timestamps({
|
||||||
|
entities = [],
|
||||||
|
setUpdatedOnCreate = true,
|
||||||
|
}: TimestampsPluginOptions): AppPlugin {
|
||||||
|
return (app: App) => ({
|
||||||
|
name: "timestamps",
|
||||||
|
schema: () => {
|
||||||
|
if (entities.length === 0) {
|
||||||
|
$console.warn("No entities specified for timestamps plugin");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const appEntities = app.em.entities.map((e) => e.name);
|
||||||
|
|
||||||
|
return em(
|
||||||
|
Object.fromEntries(
|
||||||
|
entities
|
||||||
|
.filter((e) => appEntities.includes(e))
|
||||||
|
.map((e) => [
|
||||||
|
e,
|
||||||
|
entity(e, {
|
||||||
|
created_at: datetime(),
|
||||||
|
updated_at: datetime(),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onBuilt: async () => {
|
||||||
|
app.emgr.onEvent(
|
||||||
|
DatabaseEvents.MutatorInsertBefore,
|
||||||
|
(event) => {
|
||||||
|
const { entity, data } = event.params;
|
||||||
|
if (entities.includes(entity.name)) {
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
created_at: new Date(),
|
||||||
|
updated_at: setUpdatedOnCreate ? new Date() : null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: "sync",
|
||||||
|
id: "bknd-timestamps",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
app.emgr.onEvent(
|
||||||
|
DatabaseEvents.MutatorUpdateBefore,
|
||||||
|
async (event) => {
|
||||||
|
const { entity, data } = event.params;
|
||||||
|
if (entities.includes(entity.name)) {
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
updated_at: new Date(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mode: "sync",
|
||||||
|
id: "bknd-timestamps",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -7,3 +7,4 @@ export { showRoutes, type ShowRoutesOptions } from "./dev/show-routes.plugin";
|
|||||||
export { syncConfig, type SyncConfigOptions } from "./dev/sync-config.plugin";
|
export { syncConfig, type SyncConfigOptions } from "./dev/sync-config.plugin";
|
||||||
export { syncTypes, type SyncTypesOptions } from "./dev/sync-types.plugin";
|
export { syncTypes, type SyncTypesOptions } from "./dev/sync-types.plugin";
|
||||||
export { syncSecrets, type SyncSecretsOptions } from "./dev/sync-secrets.plugin";
|
export { syncSecrets, type SyncSecretsOptions } from "./dev/sync-secrets.plugin";
|
||||||
|
export { timestamps, type TimestampsPluginOptions } from "./data/timestamps.plugin";
|
||||||
|
|||||||
Reference in New Issue
Block a user