From d9bce049ef62d1b3f0597f59237a49a87d77db27 Mon Sep 17 00:00:00 2001 From: dswbx Date: Fri, 9 Jan 2026 16:04:54 +0100 Subject: [PATCH] feat(plugin/timestamps): add indexStrategy option for entity indexing Introduced a new `indexStrategy` option in the timestamps plugin to configure index generation for `created_at` and `updated_at` fields. Supports "composite" and "individual" strategies for better control over database indexing. Added test coverage for different index strategies. --- app/src/plugins/data/timestamp.plugin.spec.ts | 50 +++++++++++++++++++ app/src/plugins/data/timestamps.plugin.ts | 36 +++++++++---- 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/app/src/plugins/data/timestamp.plugin.spec.ts b/app/src/plugins/data/timestamp.plugin.spec.ts index bdf8811..87778d9 100644 --- a/app/src/plugins/data/timestamp.plugin.spec.ts +++ b/app/src/plugins/data/timestamp.plugin.spec.ts @@ -71,4 +71,54 @@ describe("timestamps plugin", () => { expect(updatedData.updated_at).toBeDefined(); expect(updatedData.updated_at).toBeInstanceOf(Date); }); + + test("index strategy", async () => { + const app = createApp({ + config: { + data: em({ + posts: entity("posts", { + title: text(), + }), + }).toJSON(), + }, + options: { + plugins: [timestamps({ entities: ["posts"] })], + }, + }); + await app.build(); + expect(app.em.indices.length).toBe(0); + { + const app = createApp({ + config: { + data: em({ + posts: entity("posts", { + title: text(), + }), + }).toJSON(), + }, + options: { + plugins: [timestamps({ entities: ["posts"], indexStrategy: "composite" })], + }, + }); + await app.build(); + expect(app.em.indices.length).toBe(1); + } + + { + const app = createApp({ + config: { + data: em({ + posts: entity("posts", { + title: text(), + }), + }).toJSON(), + }, + options: { + plugins: [timestamps({ entities: ["posts"], indexStrategy: "individual" })], + }, + }); + await app.build(); + expect(app.em.indices.length).toBe(2); + } + }); }); diff --git a/app/src/plugins/data/timestamps.plugin.ts b/app/src/plugins/data/timestamps.plugin.ts index 0de5a94..aa22e5a 100644 --- a/app/src/plugins/data/timestamps.plugin.ts +++ b/app/src/plugins/data/timestamps.plugin.ts @@ -4,6 +4,7 @@ import { $console } from "bknd/utils"; export type TimestampsPluginOptions = { entities: string[]; setUpdatedOnCreate?: boolean; + indexStrategy?: "composite" | "individual"; }; /** @@ -19,6 +20,7 @@ export type TimestampsPluginOptions = { export function timestamps({ entities = [], setUpdatedOnCreate = true, + indexStrategy, }: TimestampsPluginOptions): AppPlugin { return (app: App) => ({ name: "timestamps", @@ -29,19 +31,35 @@ export function timestamps({ } const appEntities = app.em.entities.map((e) => e.name); + const actualEntities = entities.filter((e) => appEntities.includes(e)); return em( Object.fromEntries( - entities - .filter((e) => appEntities.includes(e)) - .map((e) => [ - e, - entity(e, { - created_at: datetime(), - updated_at: datetime(), - }), - ]), + actualEntities.map((e) => [ + e, + entity(e, { + created_at: datetime(), + updated_at: datetime(), + }), + ]), ), + (fns, schema) => { + if (indexStrategy) { + for (const entity of actualEntities) { + if (entity in schema) { + switch (indexStrategy) { + case "composite": + fns.index(schema[entity]!).on(["created_at", "updated_at"]); + break; + case "individual": + fns.index(schema[entity]!).on(["created_at"]); + fns.index(schema[entity]!).on(["updated_at"]); + break; + } + } + } + } + }, ); }, onBuilt: async () => {