Skip to content

Commit

Permalink
work on getters
Browse files Browse the repository at this point in the history
  • Loading branch information
narthur committed Apr 11, 2024
1 parent df9c4d4 commit 6b6943b
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 93 deletions.
6 changes: 4 additions & 2 deletions src/codegen.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { BaserowSdk } from "./index.js";
import { BaserowSdk, ListFieldsResponse } from "./index.js";
import fs from "fs";
import makeType from "./codegen/makeType.js";
import makeClassMethods from "./codegen/makeClassMethods.js";
import path from "path";
import { getConfig } from "./getConfig.js";

export type Table = { id: number; name: string; fields: ListFieldsResponse };

const __dirname = path.dirname(new URL(import.meta.url).pathname);

export default async function main(): Promise<void> {
Expand All @@ -20,7 +22,7 @@ export default async function main(): Promise<void> {

const sdk = new BaserowSdk(String(config.databaseToken));

const tables = await Promise.all(
const tables: Table[] = await Promise.all(
Object.entries(config.tables).map(async ([name, id]) => {
return {
name,
Expand Down
12 changes: 12 additions & 0 deletions src/codegen/makeClassMethods.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,16 @@ describe("makeClassMethods", () => {
]),
).toContain("Date");
});

it("return single select value", () => {
expect(
run([
f({
name: "the_field_name",
type: "single_select",
select_options: [{ id: 1, value: "option_1", color: "red" }],
}),
]),
).toContain(".value");
});
});
58 changes: 3 additions & 55 deletions src/codegen/makeClassMethods.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,6 @@
import { FieldDefinition, ListFieldsResponse } from "../index.js";
import { makeFieldType } from "./makeFieldType.js";
import { toCamelCase } from "./toCamelCase.js";

function makeGetter(
field: FieldDefinition,
tables: { id: number; name: string; fields: ListFieldsResponse }[],
): string {
const t = makeFieldType(field);

if (t.includes("number | string")) {
return `public ${toCamelCase(`get ${field.name}`)}(): number {
return parseFloat(this.getField<${t}>("${field.name}").toString());
}`;
}

if (field.type === "link_row") {
if (!field.link_row_table_id) {
throw new Error("link_row_table_id is missing");
}
const foreignTable = tables.find((t) => field.link_row_table_id === t.id);
if (!foreignTable) {
throw new Error("foreign table not found");
}
return `public ${toCamelCase(`get ${field.name}`)}(): Promise<${toCamelCase(foreignTable.name, true)}Row[]> {
return Promise.all(this.getField<{ "id": number, "value": string }[]>("${field.name}").map((r) => {
return this.repository.${toCamelCase(`get one ${foreignTable.name}`)}(r.id);
}));
}`;
}

if (field.type === "date" || field.formula_type === "date") {
return `public ${toCamelCase(`get ${field.name}`)}(): Date {
return new Date(this.getField<${t}>("${field.name}"));
}`;
}

return `public ${toCamelCase(`get ${field.name}`)}(): ${t} {
return this.getField<${t}>("${field.name}");
}`;
}

function makeSetter(field: FieldDefinition): string {
if (field.type === "link_row") {
return `public ${toCamelCase(`set ${field.name}`)}(value: number[]): Promise<void> {
return this.setField("${field.name}", value);
}`;
}

return `public ${toCamelCase(`set ${field.name}`)}(value: ${makeFieldType(
field,
)}): Promise<void> {
return this.setField("${field.name}", value);
}`;
}
import { ListFieldsResponse } from "../index.js";
import { makeGetter } from "./makeGetter.js";
import { makeSetter } from "./makeSetter.js";

export default function makeClassMethods(
tableId: number,
Expand Down
26 changes: 0 additions & 26 deletions src/codegen/makeFieldType.spec.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/codegen/makeFieldType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,5 @@ export function makeFieldType(field: FieldDefinition): string {
return mapPrimitive(field.formula_type);
}
}
if (field.type === "single_select") {
if (!field.select_options) {
throw new Error(
`Field ${field.name} is a single_select but has no select_options`,
);
}
return field.select_options
?.map((option) => `"${option.value}"`)
.join(" | ");
}
return mapPrimitive(field.type);
}
75 changes: 75 additions & 0 deletions src/codegen/makeGetter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { describe, it, expect } from "vitest";
import f from "../test/fixtures/fieldDefinition";
import { makeGetter } from "./makeGetter";
import { FieldDefinition } from "..";

function run(field: Partial<FieldDefinition> = {}): string {
return makeGetter(f(field), []);
}

describe("makeGetter", () => {
it.each([
[{ type: "text" }, "string"],
[{ type: "number" }, "number"],
[
{
type: "single_select",
select_options: [
{
id: 1,
value: "the_option_name",
color: "red",
},
],
},
"the_option_name",
],
[{ type: "date" }, ": Date"],
[
{
type: "single_select",
select_options: [
{
id: 1,
value: "the_option_name",
color: "red",
},
],
},
`: "the_option_name"`,
],
[
{
type: "single_select",
select_options: [
{
id: 1,
value: "the_option_name",
color: "red",
},
],
},
`<({ id: 1, value: "the_option_name", color: "red" })>`,
],
[
{
type: "single_select",
select_options: [
{
id: 1,
value: "the_option_name",
color: "red",
},
{
id: 2,
value: "the_option_name_2",
color: "blue",
},
],
},
`<({ id: 1, value: "the_option_name", color: "red" } | { id: 2, value: "the_option_name_2", color: "blue" })>`,
],
])("%s => `%s`", (field, expected) => {
expect(run(field)).toContain(expected);
});
});
103 changes: 103 additions & 0 deletions src/codegen/makeGetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Table } from "../codegen.js";
import { FieldDefinition, ListFieldsResponse } from "../index.js";
import { makeFieldType } from "./makeFieldType.js";
import { toCamelCase } from "./toCamelCase.js";

function getForeignTable(
field: FieldDefinition,
tables: Table[],
): { id: number; name: string } {
if (!field.link_row_table_id) {
throw new Error("link_row_table_id is missing");
}
const foreignTable = tables.find((t) => field.link_row_table_id === t.id);
if (!foreignTable) {
throw new Error("foreign table not found");
}
return foreignTable;
}

function getReturnType(field: FieldDefinition, tables: Table[]): string {
if (field.type === "date" || field.formula_type === "date") {
return "Date";
}

if (field.type === "link_row") {
const foreignTable = getForeignTable(field, tables);
return `Promise<${toCamelCase(foreignTable.name, true)}Row[]>`;
}

if (field.type === "single_select") {
if (!field.select_options) {
throw new Error(
`Field ${field.name} is a single_select but has no select_options`,
);
}
return field.select_options
?.map((option) => `"${option.value}"`)
.join(" | ");
}

return makeFieldType(field);
}

function getRawType(field: FieldDefinition): string {
if (field.type === "link_row") {
return `{ "id": number, "value": string }[]`;
}

if (field.type === "single_select") {
if (!field.select_options) {
throw new Error(
`Field ${field.name} is a single_select but has no select_options`,
);
}

const options = field.select_options
.map((option) => {
return `{ id: ${option.id}, value: "${option.value}", color: "${option.color}" }`;
})
.join(" | ");

return `(${options})`;
}

return makeFieldType(field);
}

function getBody(field: FieldDefinition, tables: Table[]): string {
const rawType = getRawType(field);
const query = `this.getField<${rawType}>("${field.name}")`;

if (field.type === "number") {
return `return parseFloat(${query}.toString());`;
}

if (field.type === "single_select") {
return `return ${query}.value;`;
}

if (field.type === "link_row") {
const foreignTable = getForeignTable(field, tables);
return `return Promise.all(${query}.map((r) => {
return this.repository.${toCamelCase(`get one ${foreignTable.name}`)}(r.id);
}));`;
}

if (field.type === "date" || field.formula_type === "date") {
return `return new Date(${query});`;
}

return `return ${query};`;
}

export function makeGetter(
field: FieldDefinition,
tables: { id: number; name: string; fields: ListFieldsResponse }[],
): string {
const fn = toCamelCase(`get ${field.name}`);
const rt = getReturnType(field, tables);
const bd = getBody(field, tables);

return `public ${fn}(): ${rt} { ${bd} }`;
}
17 changes: 17 additions & 0 deletions src/codegen/makeSetter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FieldDefinition } from "../index.js";
import { makeFieldType } from "./makeFieldType.js";
import { toCamelCase } from "./toCamelCase.js";

export function makeSetter(field: FieldDefinition): string {
if (field.type === "link_row") {
return `public ${toCamelCase(`set ${field.name}`)}(value: number[]): Promise<void> {
return this.setField("${field.name}", value);
}`;
}

return `public ${toCamelCase(`set ${field.name}`)}(value: ${makeFieldType(
field,
)}): Promise<void> {
return this.setField("${field.name}", value);
}`;
}

0 comments on commit 6b6943b

Please sign in to comment.