Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
b7b8c8c
chore: Use testData.length instead of a literal 1000 in the database …
Dec 30, 2024
9fb825d
chore: Have actual version in package-lock.json
Dec 30, 2024
3d3d180
chore: enable esModuleInterOp in tsconfig.json and use for supertest
Dec 30, 2024
ccb3ffa
chore: Upgrade mikro-orm to 6 only, nestjs to 10 only, and typescrip…
Dec 30, 2024
52a4ec8
chore: Bump ts-jest and supertest
Dec 30, 2024
c89b780
chore: Fix "test" script testMatch path in package.json
Dec 30, 2024
0859e8c
test: Add filter: {}, to expected throughout the spec tests
Dec 31, 2024
9b68951
chore: Remove unnecessary as any in fixColumnAlias call
Jan 2, 2025
ad71a6e
test: Add missing clone, leftJoin, and andWhere to QbTestMethodMap
Jan 2, 2025
d27b84d
test: Attempt to fix PageFactory join method test
Jan 2, 2025
400f540
fix: Remove indent rule from .eslintrc. It isn't friendly with prettier
Jan 2, 2025
8639a85
chore: Bump tsconfig target to es2021 to match nestjs 10
Jan 2, 2025
862aad6
chore: Replace this.repo as any with this.repo as unknown as QueryBui…
Jan 2, 2025
b73eb5c
refactor: Set defaults for currentPage to 1, not 0. I don't get the l…
Jan 3, 2025
124a8de
test: Quick fix to pass the url to PageFactory in page-factory.spec.ts
Jan 3, 2025
96c6ad0
refactor: Only include links in the output if there any pages
Jan 3, 2025
b3d3996
test: Add a tiny helper to page-factory spec to check for valid links…
Jan 3, 2025
f74d39d
test: Remove unused defaultPageeable from e2e-spec.ts
Jan 4, 2025
0ff73e4
test: Fix query inputs in paginate.decorator.spec. Is limit, not item…
Jan 4, 2025
893fdff
refactor: Replace triple nested ternary in paginate.decorator
Jan 4, 2025
d80a566
test: Add a defaultUrl and use it in paginate.decorator.spec
Jan 4, 2025
c496593
test: Stub out more of getRequest() iin paginate.decorator.spec
Jan 4, 2025
613c7e5
feat: A hacky attempt at changing the operand separator. (maybe not e…
Jan 4, 2025
9dce00c
chore: Add prepare script to package.json
Jan 4, 2025
fe9a638
test: Drop some commented code from e2e-spec
Jan 7, 2025
67046e8
test: Simplify the express setup in e2e-spec
Jan 7, 2025
65b15d8
test: Remove console.log from controller.getChangeOperandSeparator
Jan 7, 2025
4e63419
test: Add initial (commented) support for e2e testing with fastify
Jan 7, 2025
244faa3
Set this.query.itemsPerPage to totalItems when unpaged in page-factor…
Jan 8, 2025
b426977
fix: Only set the limit in the result if requested when unpaged is re…
Jan 8, 2025
b799cee
chore: Bump deps
Jan 21, 2025
b01605c
test: Fix page and limit param ordeing in paginatedOutput
Jan 21, 2025
765364d
refactor: Support nestjs 11, and test against 11
Jan 21, 2025
1878432
chore: Bump version to 0.5.0
Jan 21, 2025
1cc2331
fix: Temporarily force express and fastify to v5
Jan 22, 2025
ac7b533
chore: Bump deps
Mar 23, 2025
4b98cd5
refactor: Switch to NodeNext in tsconfig.json
Mar 23, 2025
54162e9
refactor: Migrate the tests to vitest from jest
Mar 23, 2025
d6528ff
chore: Upgrade to prettier 3.5.3
Mar 23, 2025
816bb56
chore: Bump husky and lint-staged
Mar 23, 2025
b52bd0d
chore: Fix some long existing (and upcoming) lint issues
Mar 23, 2025
be4ede9
chore: Switch to eslint 9
Mar 23, 2025
c6752b2
fix: Make sure limit can't be negative in page-factory.ts
Mar 24, 2025
e18b22c
test: Explicitly sort by id after sorting by DESC, nulls first
Mar 24, 2025
f2e3bd8
test: Set forceUtcTimeZone in mikro-orm config
Mar 24, 2025
d2eb44d
test: Change test date type to timestamp
Mar 24, 2025
189c6ea
chore: Replace var with const in testData.ts
Mar 24, 2025
530b8df
feat: Allow mikro-orm ^7.0.0 in peer deps
Mar 24, 2025
6b6d2ea
chore: Migrate to pnpm
May 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .eslintignore

This file was deleted.

22 changes: 0 additions & 22 deletions .eslintrc

This file was deleted.

1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public-hoist-pattern[]=sqlite3
63 changes: 43 additions & 20 deletions e2e/e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
import * as request from 'supertest';
import request, { Response as SuperAgentResponse } from 'supertest';
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { ExpressAdapter, NestExpressApplication } from '@nestjs/platform-express';
import { Application } from 'express';
import fastify, { FastifyInstance } from 'fastify';
import fastifyQs from 'fastify-qs';
import { ApplicationModule } from './src/app.module';
import { PaginateQuery, Sort } from '../src';
import { makeTestData } from './src/testData';
import { Sort } from '../src';
import { makeTestData, startDate } from './src/testData';
import { TestDto } from './src/test.dto';
import { QueryOrder } from '@mikro-orm/core';
//import { Test, TestingModule } from '@nestjs/testing';

const defaultPageable: PaginateQuery = {
currentPage: 1,
offset: 0,
itemsPerPage: 10,
unpaged: false,
totalPages: 100,
totalItems: 1000,
sortBy: [],
filter: {}
};
function isFastify(instance: object): instance is FastifyInstance {
return Object.hasOwn(instance, 'register');
}

describe('pageable', () => {
let app: NestExpressApplication;
let app: NestExpressApplication | NestFastifyApplication;
let testData: TestDto[];

beforeEach(async () => {
testData = makeTestData();
const express = require('express');
const server = express();
const adapter = new ExpressAdapter(server);
app = await NestFactory.create<NestExpressApplication>(ApplicationModule, adapter, { logger: false });

app = await NestFactory.create<NestExpressApplication>(ApplicationModule, new ExpressAdapter(), { logger: false });
//app = await NestFactory.create<NestFastifyApplication>(ApplicationModule, new FastifyAdapter(), { logger: false });
await app.init();

const instance = app.getHttpAdapter().getInstance();

if (isFastify(instance)) {
await instance.register(fastifyQs);
await instance.ready();
} else {
(instance as Application).set('query parser', 'extended');
}
});

afterEach(async () => {
Expand Down Expand Up @@ -96,6 +102,23 @@ describe('pageable', () => {
expect(response.body.data).toStrictEqual(testData.filter((data) => data.id >= 2 && data.id <= 4).map((t) => serialize(t)));
});
});
it('should support changing the operaand', () => {
const ourDatePlusFive = new Date(startDate);
ourDatePlusFive.setDate(ourDatePlusFive.getDate() + 5);
return request(app.getHttpServer())
.get(`/test/change-operand-separator?filter[updatedAt]=${encodeURIComponent(`$lt@@@${ourDatePlusFive.toISOString()}`)}`)
.expect(200)
.expect((response) => {
expect(response.body.data).toStrictEqual(
testData
.slice(0, 5)
.filter((data) => {
return data.updatedAt.getTime() <= ourDatePlusFive.getTime();
})
.map((t) => serialize(t))
);
});
});
});

describe('sorting', () => {
Expand All @@ -114,7 +137,7 @@ describe('pageable', () => {

it('should return the first page with sorting by description (DESC, nulls first)', () => {
return request(app.getHttpServer())
.get('/test?sortBy=property[description];direction[desc];nulls-first[true];')
.get('/test?sortBy=property[description];direction[desc];nulls-first[true];&sortBy=property[id];direction[asc];')
.expect(200)
.expect((response) => {
expect(response.body.data).toStrictEqual(
Expand Down Expand Up @@ -205,7 +228,7 @@ describe('pageable', () => {
});
});

describe('limit & unpaged', () => {});
// describe('limit & unpaged', () => {});
});

function serialize({ id, title, description, createdAt, updatedAt }: TestDto) {
Expand Down
10 changes: 0 additions & 10 deletions e2e/jest-e2e.json

This file was deleted.

5 changes: 5 additions & 0 deletions e2e/src/app.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ export class AppController {
getTestsMaxSize5(@Paginate({ maxSize: 5 }) pageable: PaginateQuery): Promise<PaginateResponse<TestDto>> {
return this.appService.listTests(pageable);
}

@Get('/change-operand-separator')
async getChangeOperandSeparator(@Paginate({ operandSeparator: '@@@' }) pageable: PaginateQuery): Promise<PaginateResponse<TestDto>> {
return await this.appService.listTests(pageable);
}
}
2 changes: 1 addition & 1 deletion e2e/src/db/seeders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const testData = makeTestData();

export class DatabaseSeeder extends Seeder {
async run(em: EntityManager): Promise<void> {
for (let i = 0; i < 1000; i++) {
for (let i = 0; i < testData.length; i++) {
em.create('TestEntity', {
title: testData[i].title,
description: testData[i].description,
Expand Down
4 changes: 3 additions & 1 deletion e2e/src/mikro-orm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { defineConfig } from '@mikro-orm/sqlite';
export default defineConfig({
dbName: 'e2e/src/db/test.sqlite3',
entities: ['e2e/src/**/*.entity.ts'],
forceUtcTimezone: true,
seeder: {
path: 'e2e/src/db/seeders'
}
},
dynamicImportProvider: (id) => import(id)
});
4 changes: 2 additions & 2 deletions e2e/src/test.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export class TestEntity {
title!: string;
@Property({ nullable: true })
description!: string | null;
@Property({ type: 'date', onCreate: () => new Date() })
@Property({ type: 'timestamp', onCreate: () => new Date() })
createdAt: Date = new Date();
@Property({ type: 'date', onUpdate: () => new Date() })
@Property({ type: 'timestamp', onUpdate: () => new Date() })
updatedAt: Date = new Date();
}
7 changes: 6 additions & 1 deletion e2e/src/testData.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { TestDto } from './test.dto';

export const startDate = new Date(10000000000);

export const makeTestData = (length = 1000) =>
Array.from({ length }, (_, i) => {
const id = i + 1;
return new TestDto(id, `Test ${id}`, isPrimeNumber(id) ? null : `Test ${Math.floor(id / 10)} description`, new Date(10000000000), new Date(10000000000));
const result = new Date(startDate);
result.setDate(result.getDate() + i);
return new TestDto(id, `Test ${id}`, isPrimeNumber(id) ? null : `Test ${Math.floor(id / 10)} description`, startDate, result);
//return new TestDto(id, `Test ${id}`, isPrimeNumber(id) ? null : `Test ${Math.floor(id / 10)} description`, startDate, startDate);
});

function isPrimeNumber(num: number): boolean {
Expand Down
38 changes: 38 additions & 0 deletions eslint.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import { globalIgnores } from 'eslint/config';
import prettier from 'eslint-plugin-prettier';
import simpleImportSort from 'eslint-plugin-simple-import-sort';

export default tseslint.config({
// globalIgnores(['e2e/**/*.ts', '**/*.spec.ts']),
extends: [eslint.configs.recommended, tseslint.configs.recommended],
files: ['src/**/*.ts'],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname
}
},
plugins: {
'simple-import-sort': simpleImportSort,
prettier: prettier
},
rules: {
'prettier/prettier': 'error',
'@typescript-eslint/no-unused-vars': [
'warn',
{
varsIgnorePattern: '^_',
argsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_'
}
],
curly: 'error',
'no-extra-boolean-cast': 'error',
// The codebase uses this, so this rule needs to be enabled until those are decided on
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unsafe-function-type': 'error',
'@typescript-eslint/no-empty-function': 'off'
}
});
5 changes: 0 additions & 5 deletions jest.config.js

This file was deleted.

Loading