diff --git a/docs/content/2.models/2.retrieving.md b/docs/content/2.models/2.retrieving.md index 6b50454..937e7bb 100644 --- a/docs/content/2.models/2.retrieving.md +++ b/docs/content/2.models/2.retrieving.md @@ -12,10 +12,10 @@ Once you have defined your models, you can use them to retrieve data from your d ## Retrieving All Models -To retrieve all records from a table, you can use the `query` method followed by the `get` method. +To retrieve all models from a table, you can use the `all` or `get` methods directly on the class. ```ts -const users = await User.query().get(); +const users = await User.all(); ``` ## Retrieving Single Models diff --git a/src/model/StaticForwarder.ts b/src/model/StaticForwarder.ts index 4c3b12e..2a6584d 100644 --- a/src/model/StaticForwarder.ts +++ b/src/model/StaticForwarder.ts @@ -105,6 +105,14 @@ export abstract class StaticForwarder { return (this as any).query().orderBy(column, direction); } + static async get(this: T): Promise[]> { + return (this as any).query().get(); + } + + static async all(this: T): Promise[]> { + return (this as any).query().get(); + } + static async first(this: T): Promise | undefined> { return (this as any).query().first(); } diff --git a/test/tests/Base.ts b/test/tests/Base.ts index 11d48ae..667a8a1 100644 --- a/test/tests/Base.ts +++ b/test/tests/Base.ts @@ -423,6 +423,65 @@ describe("query", () => { }); }); +describe("get and all", () => { + it("should return all records when get() is called directly on the model class", async () => { + const allPets = await Pet.query().get(); + const pets = await Pet.get(); + + expect(pets).toHaveLength(allPets.length); + expect(pets[0]).toBeInstanceOf(Pet); + expect(pets.map((pet) => pet.attributes.id).sort()).toEqual(allPets.map((pet) => pet.attributes.id).sort()); + }); + + it("should return all records when all() is called directly on the model class", async () => { + const allPets = await Pet.query().get(); + const pets = await Pet.all(); + + expect(pets).toHaveLength(allPets.length); + expect(pets[0]).toBeInstanceOf(Pet); + expect(pets.map((pet) => pet.attributes.id).sort()).toEqual(allPets.map((pet) => pet.attributes.id).sort()); + }); + + it("should infer the correct return type for get() and all()", async () => { + const getResult = await Pet.get(); + const allResult = await Pet.all(); + + // Type-level: instances must expose full Pet attributes + expect(typeof getResult[0].attributes.name).toBe("string"); + expect(typeof getResult[0].attributes.counter).toBe("number"); + expect(typeof allResult[0].attributes.id).toBe("number"); + + // @ts-expect-error - not a column on the pets table + void getResult[0].attributes.nonexistent; + // @ts-expect-error - not a column on the pets table + void allResult[0].attributes.nonexistent; + }); + + it("should chain select() with get() and narrow the result type to the selected columns", async () => { + const pets = await Pet.select(["name", "id"]).orderBy("id", "asc").get(); + + expect(pets.length).toBeGreaterThan(0); + expect(typeof pets[0].attributes.name).toBe("string"); + expect(typeof pets[0].attributes.id).toBe("number"); + + // @ts-expect-error - counter was not selected + void pets[0].attributes.counter; + // @ts-expect-error - type was not selected + void pets[0].attributes.type; + }); + + it("should chain orderBy() with get() and return results in the requested order", async () => { + const asc = await Pet.orderBy("id", "asc").get(); + const desc = await Pet.orderBy("id", "desc").get(); + + expect(asc.length).toBeGreaterThan(1); + expect(asc.length).toBe(desc.length); + expect(asc[0].attributes.id).toBeLessThan(asc[asc.length - 1].attributes.id); + expect(desc[0].attributes.id).toBeGreaterThan(desc[desc.length - 1].attributes.id); + expect(asc[0].attributes.id).toBe(desc[desc.length - 1].attributes.id); + }); +}); + describe("limit and offset", () => { it("should limit the number of results", async () => { const pets = await Pet.limit(1).get();