5ed3d2bc5f
First-party booking system on top of Stalwart calendars (no third-party scheduling dependency). Hosts expose public booking pages; visitors pick a slot computed from the host's live Stalwart free/busy, and confirming writes the event to the host's calendar and sends a dezky-branded confirmation with an .ics. platform-api (services/platform-api/src/scheduling): - Schemas: Host, StalwartCredential (AES-256-GCM at rest), AvailabilitySchedule, EventType, Booking, SlotLock (unique (hostId,startUtc) + TTL). - StalwartCalendarModule: JMAP gateway (free/busy via Principal/getAvailability, event create/delete, scheduleAgent=client) + on-behalf app-password provisioning. CredentialCipher for at-rest encryption. - DST-correct slot engine (Luxon) with unit tests; two-layer double-booking guard (atomic SlotLock + live free/busy re-check). - Booking confirm/cancel/reschedule, branded email + .ics via JMAP submission, self-service manage tokens. /api/v1 public + tenant-gated admin routes, per-IP rate limiting. apps/booking: standalone public, whitelabel booking app (booking.dezky.eu) — path-based tenant resolution, per-tenant brand colour, booking + manage flows. apps/portal: admin scheduling page (hosts, event types, availability, bookings with edit/delete + admin cancel/reschedule) and proxy routes. infra: booking dev service in docker-compose; scheduling env vars.
33 lines
1.0 KiB
JavaScript
33 lines
1.0 KiB
JavaScript
// Jest (ESM + TypeScript via ts-jest). The codebase is NodeNext ESM with `.js`
|
|
// import specifiers, so we strip the extension in moduleNameMapper to resolve
|
|
// `./x.js` → `./x.ts` under jest. Run with NODE_OPTIONS=--experimental-vm-modules
|
|
// (set in the package.json "test" script).
|
|
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
export default {
|
|
testEnvironment: 'node',
|
|
roots: ['<rootDir>/src'],
|
|
testMatch: ['**/?(*.)+(spec).ts'],
|
|
extensionsToTreatAsEsm: ['.ts'],
|
|
moduleNameMapper: {
|
|
'^(\\.{1,2}/.*)\\.js$': '$1',
|
|
},
|
|
transform: {
|
|
'^.+\\.ts$': [
|
|
'ts-jest',
|
|
{
|
|
useESM: true,
|
|
tsconfig: {
|
|
// Emit ESM regardless of package.json "type" (NodeNext would emit CJS
|
|
// here and break under jest's ESM VM → "exports is not defined").
|
|
module: 'ESNext',
|
|
moduleResolution: 'Bundler',
|
|
isolatedModules: true,
|
|
experimentalDecorators: true,
|
|
emitDecoratorMetadata: true,
|
|
verbatimModuleSyntax: false,
|
|
},
|
|
},
|
|
],
|
|
},
|
|
}
|