mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-22 06:41:46 +00:00
0b218d53b2
Co-hosted NestJS app behind the existing Express server via a strangler-fig dispatcher, sharing the same better-sqlite3 connection and JWT httpOnly cookie. Additive and dormant: default routing stays on Express, Nest only serves its own /api/_nest diagnostics until a module opts in. F1 @trek/shared Zod contract package; F2 Nest bootstrap co-hosted (fall-through, single Dockerfile/port); F3 shared better-sqlite3 provider; F4 JWT cookie auth guard (+ @CurrentUser, admin guard); F5 Zod validation pipe + error-envelope parity; F6 Nest test + coverage gates; F7 per-prefix strangler toggle (env, default Express); F8 CI build/typecheck/test/coverage. Remaining F4/F6/F8 checklist items (trip-access + permission levels + MFA policy, e2e harness/seed + 80% gate, Nest↔Express parity test, Playwright PR-comment workflow) are tracked on the first consuming module cards (L1/A1/C1).
40 lines
1.6 KiB
TypeScript
40 lines
1.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { idSchema, idParamSchema, nonEmptyString, isoDateTime } from './primitives.schema';
|
|
import { paginationQuerySchema } from './pagination.schema';
|
|
|
|
describe('@trek/shared primitives', () => {
|
|
it('idSchema accepts positive integers, rejects others', () => {
|
|
expect(idSchema.parse(1)).toBe(1);
|
|
expect(idSchema.safeParse(0).success).toBe(false);
|
|
expect(idSchema.safeParse(-3).success).toBe(false);
|
|
expect(idSchema.safeParse(1.5).success).toBe(false);
|
|
});
|
|
|
|
it('idParamSchema coerces string params to a positive int', () => {
|
|
expect(idParamSchema.parse('42')).toBe(42);
|
|
expect(idParamSchema.safeParse('abc').success).toBe(false);
|
|
});
|
|
|
|
it('nonEmptyString trims and rejects empty', () => {
|
|
expect(nonEmptyString.parse(' hi ')).toBe('hi');
|
|
expect(nonEmptyString.safeParse(' ').success).toBe(false);
|
|
});
|
|
|
|
it('isoDateTime accepts an ISO timestamp', () => {
|
|
expect(isoDateTime.safeParse('2026-05-25T08:38:14Z').success).toBe(true);
|
|
expect(isoDateTime.safeParse('not-a-date').success).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('@trek/shared pagination', () => {
|
|
it('applies defaults and coerces', () => {
|
|
expect(paginationQuerySchema.parse({})).toEqual({ page: 1, perPage: 50 });
|
|
expect(paginationQuerySchema.parse({ page: '2', perPage: '10' })).toEqual({ page: 2, perPage: 10 });
|
|
});
|
|
|
|
it('enforces bounds', () => {
|
|
expect(paginationQuerySchema.safeParse({ perPage: 0 }).success).toBe(false);
|
|
expect(paginationQuerySchema.safeParse({ perPage: 999 }).success).toBe(false);
|
|
});
|
|
});
|