From 079f30cfd89075c80a9fdd999b7cedc0f85e6a1b Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Wed, 17 Apr 2024 12:58:39 -0400 Subject: [PATCH 1/2] optimize link_row fetching --- src/codegen/makeGetter.spec.ts | 8 ++++++++ src/codegen/makeGetter.ts | 2 +- src/codegen/makeModelMethods.spec.ts | 13 ------------- src/codegen/makeRepositoryMethods.ts | 4 +--- src/factory.ts | 27 +++++++++++++++++++++------ src/index.ts | 1 + src/row.ts | 27 +++++++++++++++++++++++++-- src/types.ts | 10 ++++++++++ 8 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/codegen/makeGetter.spec.ts b/src/codegen/makeGetter.spec.ts index d4fd6e4..f88544e 100644 --- a/src/codegen/makeGetter.spec.ts +++ b/src/codegen/makeGetter.spec.ts @@ -84,6 +84,14 @@ describe("makeGetter", () => { }, `parseFloat(`, ], + [ + { + type: "link_row", + link_row_table_id: 1, + link_row_related_field_id: 2, + }, + "this.repository.getMany<", + ], ])("%s => `%s`", (field, expected) => { expect(run(field)).toContain(expected); }); diff --git a/src/codegen/makeGetter.ts b/src/codegen/makeGetter.ts index 6ff2ee2..e7b3b38 100644 --- a/src/codegen/makeGetter.ts +++ b/src/codegen/makeGetter.ts @@ -59,7 +59,7 @@ function getBody(field: FieldDefinition, tables: Table[]): string { if (field.type === "link_row") { const foreignTable = getForeignTable(field, tables); - return `return Promise.all(${query}.map((r) => this.repository.${toCamelCase(`get one ${foreignTable.name}`)}(r.id)));`; + return `return this.getLinkedRows(${field.link_row_table_id}, ${field.link_row_related_field_id}, ${foreignTable.name}Row);`; } if (field.type === "date" || field.formula_type === "date") { diff --git a/src/codegen/makeModelMethods.spec.ts b/src/codegen/makeModelMethods.spec.ts index 742e120..0f71f4c 100644 --- a/src/codegen/makeModelMethods.spec.ts +++ b/src/codegen/makeModelMethods.spec.ts @@ -145,19 +145,6 @@ describe("makeClassMethods", () => { ).toContain("value: number[]"); }); - it("uses repository to get linked row objects", () => { - expect( - makeModelMethods(1, [ - { - id: 1, - name: "the_table_name", - fields: [f({ type: "link_row", link_row_table_id: 2 })], - }, - { id: 2, name: "the_foreign_table_name", fields: [] }, - ]), - ).toContain("this.repository.getOneTheForeignTableName"); - }); - it("properly set link row getter return type", () => { expect( makeModelMethods(1, [ diff --git a/src/codegen/makeRepositoryMethods.ts b/src/codegen/makeRepositoryMethods.ts index 28a54e8..4c9912a 100644 --- a/src/codegen/makeRepositoryMethods.ts +++ b/src/codegen/makeRepositoryMethods.ts @@ -4,9 +4,7 @@ export default function makeRepositoryMethods(tables: Table[]): string { return tables .map(({ id, name }) => { return ` public async getMany${name}(options: ListRowsOptions = {}): Promise { - const { results } = await this.sdk.listRows<${name}RowType>(${id}, options); - const rowClass = this.getRowClass(${id}) || ${name}Row; - return results.map((row) => new rowClass({ tableId: ${id}, rowId: row.id, row, sdk: this.sdk, repository: this })) as T[]; + return this.getMany(${id}, ${name}Row, options); } public async getOne${name}(id: number, options: GetRowOptions = {}): Promise { diff --git a/src/factory.ts b/src/factory.ts index 866260c..5cce1b2 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -1,10 +1,6 @@ import { BaserowConfig, getConfig } from "./getConfig.js"; -import { BaserowSdk } from "./index.js"; -import { Row, RowOptions, RowType } from "./row.js"; - -interface RowClass { - new (options: RowOptions): Row; -} +import { BaserowSdk, RowClass } from "./index.js"; +import { Row, RowType } from "./row.js"; export abstract class Factory { public readonly config: BaserowConfig; @@ -32,4 +28,23 @@ export abstract class Factory { ): RowClass | undefined { return this.classes.get(tableId) as RowClass | undefined; } + + public async getMany( + tableId: number, + defaultClass: RowClass, + options: Record = {}, + ): Promise { + const { results } = await this.sdk.listRows(tableId, options); + const rowClass = this.getRowClass(tableId) || defaultClass; + return results.map( + (row) => + new rowClass({ + tableId, + rowId: row.id, + row, + sdk: this.sdk, + repository: this as unknown as F, + }), + ) as T[]; + } } diff --git a/src/index.ts b/src/index.ts index bff4ce1..de8086d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,6 +49,7 @@ export type FieldDefinition = { array_formula_type?: string; formula_type?: string; link_row_table_id?: number; + link_row_related_field_id?: number; select_options?: { id: number; value: string; color: string }[]; }; diff --git a/src/row.ts b/src/row.ts index 40433a8..acda408 100644 --- a/src/row.ts +++ b/src/row.ts @@ -1,5 +1,5 @@ import { Factory } from "./factory.js"; -import { BaserowSdk } from "./index.js"; +import { BaserowSdk, RowClass } from "./index.js"; export type RowType = Record & { id: number; order: string }; export type RowOptions = { @@ -9,7 +9,10 @@ export type RowOptions = { sdk: BaserowSdk; repository: R; }; -export abstract class Row { +export abstract class Row< + T extends RowType = RowType, + R extends Factory = Factory, +> { protected tableId: number; protected rowId: number; protected row: T; @@ -46,4 +49,24 @@ export abstract class Row { [field]: value, }); } + + protected getLinkedRows( + tableId: number, + field: string | number, + defaultClass: RowClass, + ): Promise { + return this.repository.getMany(tableId, defaultClass, { + filters: { + filter_type: "AND", + filters: [ + { + type: "link_row_has", + field: field.toString(), + value: this.getId().toString(), + }, + ], + groups: [], + }, + }); + } } diff --git a/src/types.ts b/src/types.ts index 4478cbc..45d4230 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,14 @@ +import { Factory } from "./factory.js"; +import { Row, RowOptions, RowType } from "./row.js"; + export type FieldValue = | T | { id: number; value: T } | { ids: Record; value: T }; + +export interface RowClass< + T extends RowType = RowType, + R extends Factory = Factory, +> { + new (options: RowOptions): Row; +} From d58e3b678906988aeda59308c619507de91a8e2c Mon Sep 17 00:00:00 2001 From: Nathan Arthur Date: Wed, 17 Apr 2024 13:00:50 -0400 Subject: [PATCH 2/2] fix test --- src/codegen/makeGetter.spec.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/codegen/makeGetter.spec.ts b/src/codegen/makeGetter.spec.ts index f88544e..831e824 100644 --- a/src/codegen/makeGetter.spec.ts +++ b/src/codegen/makeGetter.spec.ts @@ -4,7 +4,13 @@ import { makeGetter } from "./makeGetter"; import { FieldDefinition } from ".."; function run(field: Partial = {}): string { - return makeGetter(f(field), []); + return makeGetter(f(field), [ + { + id: 1, + name: "table_name", + fields: [], + }, + ]); } describe("makeGetter", () => { @@ -90,7 +96,7 @@ describe("makeGetter", () => { link_row_table_id: 1, link_row_related_field_id: 2, }, - "this.repository.getMany<", + "this.getLinkedRows", ], ])("%s => `%s`", (field, expected) => { expect(run(field)).toContain(expected);