diff --git a/libs/tools/src/generators/api-feature/__snapshots__/api-feature-generator.spec.ts.snap b/libs/tools/src/generators/api-feature/__snapshots__/api-feature-generator.spec.ts.snap index e8ce2c7..5644ed5 100644 --- a/libs/tools/src/generators/api-feature/__snapshots__/api-feature-generator.spec.ts.snap +++ b/libs/tools/src/generators/api-feature/__snapshots__/api-feature-generator.spec.ts.snap @@ -4,6 +4,7 @@ exports[`api-feature generator should generate the feature libraries 1`] = ` "export * from './lib/api-test-data-access.module'; export * from './lib/api-test.service'; export * from './lib/entity/test.entity'; +export * from './lib/entity/test-paging.entity'; export * from './lib/dto/admin-create-test.input'; export * from './lib/dto/admin-find-many-test.input'; export * from './lib/dto/admin-update-test.input'; @@ -16,6 +17,7 @@ import { ApiCoreService } from '@proj/api/core/data-access'; import { AdminCreateTestInput } from './dto/admin-create-test.input'; import { AdminFindManyTestInput } from './dto/admin-find-many-test.input'; import { AdminUpdateTestInput } from './dto/admin-update-test.input'; +import { TestPaging } from './entity/test-paging.entity'; import { parseAdminFindManyTest } from './helpers/parse-admin-find-many-test'; @Injectable() @@ -31,24 +33,12 @@ export class ApiTestAdminService { return !!deleted; } - async findManyTest(input: AdminFindManyTestInput) { - const { where, orderBy, take, skip } = parseAdminFindManyTest(input); - const items = await this.core.data.test.findMany({ - where, - orderBy, - take, - skip, - }); - return items ?? []; - } - - async findManyTestCount(input: AdminFindManyTestInput) { - const { where, orderBy, take, skip } = parseAdminFindManyTest(input); - const [count, total] = await Promise.all([ - this.core.data.test.count({ where, orderBy, take, skip }), - this.core.data.test.count({ where, orderBy }), - ]); - return { count, skip, take, total }; + async findManyTest(input: AdminFindManyTestInput): Promise { + const { where, orderBy, limit, page } = parseAdminFindManyTest(input); + const [data, meta] = await this.core.data.test + .paginate({ where, orderBy }) + .withPages({ limit, page }); + return { data, meta }; } async findOneTest(testId: string) { @@ -106,15 +96,12 @@ export class AdminCreateTestInput { exports[`api-feature generator should generate the feature libraries 6`] = ` "import { Field, InputType, Int } from '@nestjs/graphql'; +import { PagingInput } from '@proj/api/core/data-access'; @InputType() -export class AdminFindManyTestInput { +export class AdminFindManyTestInput extends PagingInput() { @Field({ nullable: true }) search?: string; - @Field(() => Int, { nullable: true, defaultValue: 0 }) - skip?: number; - @Field(() => Int, { nullable: true, defaultValue: 10 }) - take?: number; } " `; @@ -135,9 +122,9 @@ exports[`api-feature generator should generate the feature libraries 8`] = ` import { AdminFindManyTestInput } from '../dto/admin-find-many-test.input'; export function parseAdminFindManyTest(input: AdminFindManyTestInput): { + limit: number; orderBy: Prisma.TestOrderByWithRelationInput; - skip?: number; - take?: number; + page: number; where: Prisma.TestWhereInput; } { const where: Prisma.TestWhereInput = {}; @@ -150,10 +137,10 @@ export function parseAdminFindManyTest(input: AdminFindManyTestInput): { } return { - where, - skip: input.skip ?? 0, - take: input.take ?? 10, + limit: input.limit ?? 10, orderBy: { name: 'asc' }, + page: input.page ?? 1, + where, }; } " @@ -185,13 +172,13 @@ exports[`api-feature generator should generate the feature libraries 11`] = ` "import { Resolver } from '@nestjs/graphql'; import { ApiTestService } from '@proj/api/test/data-access'; import { ApiAuthGraphQLAdminGuard } from '@proj/api/auth/data-access'; -import { Paging } from '@proj/api/core/data-access'; import { Mutation, Query, Args } from '@nestjs/graphql'; import { UseGuards } from '@nestjs/common'; import { AdminCreateTestInput, AdminFindManyTestInput, Test, + TestPaging, AdminUpdateTestInput, } from '@proj/api/test/data-access'; @@ -210,16 +197,11 @@ export class ApiTestAdminResolver { return this.service.admin.deleteTest(testId); } - @Query(() => [Test], { nullable: true }) + @Query(() => TestPaging, { nullable: true }) adminFindManyTest(@Args('input') input: AdminFindManyTestInput) { return this.service.admin.findManyTest(input); } - @Query(() => Paging, { nullable: true }) - adminFindManyTestCount(@Args('input') input: AdminFindManyTestInput) { - return this.service.admin.findManyTestCount(input); - } - @Query(() => Test, { nullable: true }) adminFindOneTest(@Args('testId') testId: string) { return this.service.admin.findOneTest(testId); diff --git a/libs/tools/src/lib/api/files/data-access/lib/api-__modelFileName__-__adminFileName__.service.ts.template b/libs/tools/src/lib/api/files/data-access/lib/api-__modelFileName__-__adminFileName__.service.ts.template index c052ea5..106957a 100644 --- a/libs/tools/src/lib/api/files/data-access/lib/api-__modelFileName__-__adminFileName__.service.ts.template +++ b/libs/tools/src/lib/api/files/data-access/lib/api-__modelFileName__-__adminFileName__.service.ts.template @@ -3,6 +3,7 @@ import { ApiCoreService } from '@<%= npmScope %>/api/core/data-access' import { <%= admin.className %>Create<%= model.className %>Input } from './dto/<%= admin.fileName %>-create-<%= model.fileName %>.input' import { <%= admin.className %>FindMany<%= model.className %>Input } from './dto/<%= admin.fileName %>-find-many-<%= model.fileName %>.input' import { <%= admin.className %>Update<%= model.className %>Input } from './dto/<%= admin.fileName %>-update-<%= model.fileName %>.input' +import { <%= model.className %>Paging } from './entity/<%= model.fileName %>-paging.entity' import { parse<%= admin.className %>FindMany<%= model.className %> } from './helpers/parse-<%= admin.fileName %>-find-many-<%= model.fileName %>' @Injectable() @@ -18,19 +19,10 @@ export class Api<%= model.className %><%= admin.className %>Service { return !!deleted } - async findMany<%= model.className %>(input: <%= admin.className %>FindMany<%= model.className %>Input) { - const { where, orderBy, take, skip } = parse<%= admin.className %>FindMany<%= model.className %>(input) - const items = await this.core.data.<%= model.propertyName %>.findMany({ where, orderBy, take, skip }) - return items ?? [] - } - - async findMany<%= model.className %>Count(input: <%= admin.className %>FindMany<%= model.className %>Input) { - const { where, orderBy, take, skip } = parse<%= admin.className %>FindMany<%= model.className %>(input) - const [count, total] = await Promise.all([ - this.core.data.<%= model.propertyName %>.count({ where, orderBy, take, skip }), - this.core.data.<%= model.propertyName %>.count({ where, orderBy }), - ]) - return { count, skip, take, total } + async findMany<%= model.className %>(input: <%= admin.className %>FindMany<%= model.className %>Input): Promise<<%= model.className %>Paging> { + const { where, orderBy, limit, page } = parse<%= admin.className %>FindMany<%= model.className %>(input) + const [data, meta] = await this.core.data.<%= model.propertyName %>.paginate({ where, orderBy }).withPages({ limit, page }) + return { data, meta } } async findOne<%= model.className %>(<%= model.propertyName %>Id: string) { diff --git a/libs/tools/src/lib/api/files/data-access/lib/dto/__adminFileName__-find-many-__modelFileName__.input.ts.template b/libs/tools/src/lib/api/files/data-access/lib/dto/__adminFileName__-find-many-__modelFileName__.input.ts.template index 084a575..21a188f 100644 --- a/libs/tools/src/lib/api/files/data-access/lib/dto/__adminFileName__-find-many-__modelFileName__.input.ts.template +++ b/libs/tools/src/lib/api/files/data-access/lib/dto/__adminFileName__-find-many-__modelFileName__.input.ts.template @@ -1,11 +1,8 @@ import { Field, InputType, Int } from '@nestjs/graphql' +import { PagingInput } from '@<%= npmScope %>/api/core/data-access' @InputType() -export class <%= admin.className %>FindMany<%= model.className %>Input { +export class <%= admin.className %>FindMany<%= model.className %>Input extends PagingInput() { @Field({ nullable: true }) search?: string - @Field(() => Int, { nullable: true, defaultValue: 0 }) - skip?: number - @Field(() => Int, { nullable: true, defaultValue: 10 }) - take?: number } diff --git a/libs/tools/src/lib/api/files/data-access/lib/entity/__modelFileName__-paging.entity.ts.template b/libs/tools/src/lib/api/files/data-access/lib/entity/__modelFileName__-paging.entity.ts.template new file mode 100644 index 0000000..aba1316 --- /dev/null +++ b/libs/tools/src/lib/api/files/data-access/lib/entity/__modelFileName__-paging.entity.ts.template @@ -0,0 +1,6 @@ +import { ObjectType } from '@nestjs/graphql' +import { PagingResponse } from '@<%= npmScope %>/api/core/data-access' +import { <%= model.className %> } from './<%= model.fileName %>.entity' + +@ObjectType() +export class <%= model.className %>Paging extends PagingResponse<<%= model.className %>>(<%= model.className %>) {} diff --git a/libs/tools/src/lib/api/files/data-access/lib/helpers/parse-__adminFileName__-find-many-__modelFileName__.ts.template b/libs/tools/src/lib/api/files/data-access/lib/helpers/parse-__adminFileName__-find-many-__modelFileName__.ts.template index ca998d9..9388509 100644 --- a/libs/tools/src/lib/api/files/data-access/lib/helpers/parse-__adminFileName__-find-many-__modelFileName__.ts.template +++ b/libs/tools/src/lib/api/files/data-access/lib/helpers/parse-__adminFileName__-find-many-__modelFileName__.ts.template @@ -2,9 +2,9 @@ import { Prisma } from '@prisma/client' import { <%= admin.className %>FindMany<%= model.className %>Input } from '../dto/<%= admin.fileName %>-find-many-<%= model.fileName %>.input' export function parse<%= admin.className %>FindMany<%= model.className %>(input: <%= admin.className %>FindMany<%= model.className %>Input): { + limit: number orderBy: Prisma.<%= model.className %>OrderByWithRelationInput - skip?: number - take?: number + page: number where: Prisma.<%= model.className %>WhereInput } { const where: Prisma.<%= model.className %>WhereInput = {} @@ -17,9 +17,9 @@ export function parse<%= admin.className %>FindMany<%= model.className %>(input: } return { - where, - skip: input.skip ?? 0, - take: input.take ?? 10, + limit: input.limit ?? 10, orderBy: { <%= label.propertyName %>: 'asc' }, + page: input.page ?? 1, + where, } } diff --git a/libs/tools/src/lib/api/files/feature/lib/api-__modelFileName__-__adminFileName__.resolver.ts.template b/libs/tools/src/lib/api/files/feature/lib/api-__modelFileName__-__adminFileName__.resolver.ts.template index f254698..d0851dd 100644 --- a/libs/tools/src/lib/api/files/feature/lib/api-__modelFileName__-__adminFileName__.resolver.ts.template +++ b/libs/tools/src/lib/api/files/feature/lib/api-__modelFileName__-__adminFileName__.resolver.ts.template @@ -1,13 +1,13 @@ import { Resolver } from '@nestjs/graphql' import { <%= app.className %><%= model.className %>Service } from '@<%= npmScope %>/<%= app.fileName %>/<%= model.fileName %>/data-access' import { <%= app.className %>AuthGraphQLAdminGuard } from '@<%= npmScope %>/<%= app.fileName %>/auth/data-access' -import { Paging } from '@<%= npmScope %>/<%= app.fileName %>/core/data-access' import { Mutation, Query, Args } from '@nestjs/graphql' import { UseGuards } from '@nestjs/common' import { <%= admin.className %>Create<%= model.className %>Input, <%= admin.className %>FindMany<%= model.className %>Input, <%= model.className %>, + <%= model.className %>Paging, <%= admin.className %>Update<%= model.className %>Input, } from '@<%= npmScope %>/<%= app.fileName %>/<%= model.fileName %>/data-access' @@ -26,16 +26,11 @@ export class <%= app.className %><%= model.className %><%= admin.className %>Res return this.service.<%= admin.propertyName %>.delete<%= model.className %>(<%= model.propertyName %>Id) } - @Query(() => [<%= model.className %>], { nullable: true }) + @Query(() => <%= model.className %>Paging, { nullable: true }) <%= admin.propertyName %>FindMany<%= model.className %>(@Args('input') input: <%= admin.className %>FindMany<%= model.className %>Input) { return this.service.<%= admin.propertyName %>.findMany<%= model.className %>(input) } - @Query(() => Paging, { nullable: true }) - <%= admin.propertyName %>FindMany<%= model.className %>Count(@Args('input') input: <%= admin.className %>FindMany<%= model.className %>Input) { - return this.service.<%= admin.propertyName %>.findMany<%= model.className %>Count(input) - } - @Query(() => <%= model.className %>, { nullable: true }) <%= admin.propertyName %>FindOne<%= model.className %>(@Args('<%= model.propertyName %>Id') <%= model.propertyName %>Id: string) { return this.service.<%= admin.propertyName %>.findOne<%= model.className %>(<%= model.propertyName %>Id) diff --git a/libs/tools/src/lib/api/generate-api-lib-data-access.ts b/libs/tools/src/lib/api/generate-api-lib-data-access.ts index 04cfcfd..b12c730 100644 --- a/libs/tools/src/lib/api/generate-api-lib-data-access.ts +++ b/libs/tools/src/lib/api/generate-api-lib-data-access.ts @@ -12,6 +12,7 @@ export async function generateApiLibDataAccess(tree: Tree, options: NormalizedAp const dataAccessExports: string[] = [ `./lib/${options.app}-${options.name}.service`, `./lib/entity/${substitutions.model.fileName}.entity`, + `./lib/entity/${substitutions.model.fileName}-paging.entity`, ] if (!options.skipAdminCrud) { diff --git a/libs/tools/src/lib/api/generate-sdk-file.ts b/libs/tools/src/lib/api/generate-sdk-file.ts index dc174bf..aa7b614 100644 --- a/libs/tools/src/lib/api/generate-sdk-file.ts +++ b/libs/tools/src/lib/api/generate-sdk-file.ts @@ -31,11 +31,13 @@ function sdkTemplate(name: string, label: string) { } query adminFindMany${className}($input: AdminFindMany${className}Input!) { - count: adminFindMany${className}Count(input: $input) { - ...PagingDetails - } - items: adminFindMany${className}(input: $input) { - ...${className}Details + paging: adminFindMany${className}(input: $input) { + data { + ...${className}Details + } + meta { + ...PagingMetaDetails + } } } diff --git a/libs/tools/src/lib/web/files/data-access/lib/use-admin-find-many-__modelFileName__.tsx.template b/libs/tools/src/lib/web/files/data-access/lib/use-admin-find-many-__modelFileName__.tsx.template index 64fe9f1..f0ca1eb 100644 --- a/libs/tools/src/lib/web/files/data-access/lib/use-admin-find-many-__modelFileName__.tsx.template +++ b/libs/tools/src/lib/web/files/data-access/lib/use-admin-find-many-__modelFileName__.tsx.template @@ -8,13 +8,13 @@ import { useState } from 'react' export function useAdminFindMany<%= modelClassName %>(props?: PartialInput>) { const sdk = useWebSdk() - const [take, setTake] = useState(props?.take ?? 10) - const [skip, setSkip] = useState(props?.skip ?? 0) + const [limit, setLimit] = useState(10) + const [page, setPage] = useState(1) const [search, setSearch] = useState(props?.search ?? '') - const input: AdminFindMany<%= modelClassName %>Input = { skip, take, search } + const input: AdminFindMany<%= modelClassName %>Input = { page, limit, search } const query = useQuery(['admin', 'find-many-<%= modelPropertyName %>', input], () => sdk.adminFindMany<%= modelClassName %>({ input }).then((res) => res.data)) - const total = query.data?.count?.total ?? 0 + const total = query.data?.paging?.meta?.totalCount ?? 0 return { create<%= modelClassName %>: (input: AdminCreate<%= modelClassName %>Input) => @@ -41,10 +41,10 @@ export function useAdminFindMany<%= modelClassName %>(props?: PartialListFeature() { {query.isLoading ? ( - ) : query?.data?.items?.length ? ( + ) : query?.data?.paging?.data?.length ? ( Table delete<%= modelClassName %>={(<%= modelPropertyName %>) => { if (!window.confirm('Are you sure?')) return return delete<%= modelClassName %>(<%= modelPropertyName %>.id) }} - <%= modelPropertyName %>s={query?.data?.items as <%= modelClassName %>[]} + <%= modelPropertyName %>s={query?.data?.paging?.data ?? []} /> ) : ( - + )}