@rvoh/psychic 2.3.8 → 3.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/cjs/src/cli/index.js +4 -0
  2. package/dist/cjs/src/controller/helpers/logIfDevelopment.js +5 -5
  3. package/dist/cjs/src/controller/index.js +119 -40
  4. package/dist/cjs/src/devtools/helpers/launchDevServer.js +15 -1
  5. package/dist/cjs/src/error/openapi/UnrecognizedDbTypeFoundWhileComputingOpenapiAttribute.js +44 -0
  6. package/dist/cjs/src/error/router/cannot-commit-routes-without-koa-app.js +12 -0
  7. package/dist/cjs/src/helpers/toJson.js +2 -8
  8. package/dist/cjs/src/helpers/validateOpenApiSchema.js +1 -1
  9. package/dist/cjs/src/openapi-renderer/SerializerOpenapiRenderer.js +2 -2
  10. package/dist/cjs/src/openapi-renderer/endpoint.js +2 -2
  11. package/dist/cjs/src/openapi-renderer/helpers/OpenapiPayloadValidator.js +75 -9
  12. package/dist/cjs/src/openapi-renderer/helpers/{dreamAttributeOpenapiShape.js → dreamColumnOpenapiShape.js} +19 -6
  13. package/dist/cjs/src/openapi-renderer/helpers/stringify-cache.js +55 -0
  14. package/dist/cjs/src/openapi-renderer/helpers/validator-cache.js +52 -0
  15. package/dist/cjs/src/psychic-app/helpers/import/importControllers.js +1 -1
  16. package/dist/cjs/src/psychic-app/index.js +3 -10
  17. package/dist/cjs/src/router/index.js +31 -25
  18. package/dist/cjs/src/server/helpers/startPsychicServer.js +6 -2
  19. package/dist/cjs/src/server/index.js +32 -35
  20. package/dist/cjs/src/server/params.js +56 -3
  21. package/dist/cjs/src/session/index.js +9 -12
  22. package/dist/esm/src/cli/index.js +4 -0
  23. package/dist/esm/src/controller/helpers/logIfDevelopment.js +5 -5
  24. package/dist/esm/src/controller/index.js +119 -40
  25. package/dist/esm/src/devtools/helpers/launchDevServer.js +15 -1
  26. package/dist/esm/src/error/openapi/UnrecognizedDbTypeFoundWhileComputingOpenapiAttribute.js +44 -0
  27. package/dist/esm/src/error/router/cannot-commit-routes-without-koa-app.js +12 -0
  28. package/dist/esm/src/helpers/toJson.js +2 -8
  29. package/dist/esm/src/helpers/validateOpenApiSchema.js +1 -1
  30. package/dist/esm/src/openapi-renderer/SerializerOpenapiRenderer.js +2 -2
  31. package/dist/esm/src/openapi-renderer/endpoint.js +2 -2
  32. package/dist/esm/src/openapi-renderer/helpers/OpenapiPayloadValidator.js +75 -9
  33. package/dist/esm/src/openapi-renderer/helpers/{dreamAttributeOpenapiShape.js → dreamColumnOpenapiShape.js} +19 -6
  34. package/dist/esm/src/openapi-renderer/helpers/stringify-cache.js +55 -0
  35. package/dist/esm/src/openapi-renderer/helpers/validator-cache.js +52 -0
  36. package/dist/esm/src/psychic-app/helpers/import/importControllers.js +1 -1
  37. package/dist/esm/src/psychic-app/index.js +3 -10
  38. package/dist/esm/src/router/index.js +31 -25
  39. package/dist/esm/src/server/helpers/startPsychicServer.js +6 -2
  40. package/dist/esm/src/server/index.js +32 -35
  41. package/dist/esm/src/server/params.js +56 -3
  42. package/dist/esm/src/session/index.js +9 -12
  43. package/dist/types/src/controller/helpers/logIfDevelopment.d.ts +3 -4
  44. package/dist/types/src/controller/index.d.ts +19 -8
  45. package/dist/types/src/devtools/helpers/launchDevServer.d.ts +2 -1
  46. package/dist/types/src/error/openapi/UnrecognizedDbTypeFoundWhileComputingOpenapiAttribute.d.ts +7 -0
  47. package/dist/types/src/error/router/cannot-commit-routes-without-koa-app.d.ts +3 -0
  48. package/dist/types/src/helpers/cookieMaxAgeFromCookieOpts.d.ts +1 -1
  49. package/dist/types/src/helpers/toJson.d.ts +1 -1
  50. package/dist/types/src/helpers/validateOpenApiSchema.d.ts +5 -1
  51. package/dist/types/src/openapi-renderer/helpers/OpenapiPayloadValidator.d.ts +41 -0
  52. package/dist/types/src/openapi-renderer/helpers/{dreamAttributeOpenapiShape.d.ts → dreamColumnOpenapiShape.d.ts} +1 -1
  53. package/dist/types/src/openapi-renderer/helpers/stringify-cache.d.ts +34 -0
  54. package/dist/types/src/openapi-renderer/helpers/validator-cache.d.ts +35 -0
  55. package/dist/types/src/psychic-app/index.d.ts +11 -14
  56. package/dist/types/src/router/index.d.ts +17 -17
  57. package/dist/types/src/router/route-manager.d.ts +4 -3
  58. package/dist/types/src/server/helpers/startPsychicServer.d.ts +3 -3
  59. package/dist/types/src/server/index.d.ts +3 -3
  60. package/dist/types/src/server/params.d.ts +2 -2
  61. package/dist/types/src/session/index.d.ts +13 -5
  62. package/package.json +30 -19
  63. package/dist/cjs/src/error/router/cannot-commit-routes-without-express-app.js +0 -12
  64. package/dist/esm/src/error/router/cannot-commit-routes-without-express-app.js +0 -12
  65. package/dist/types/src/error/router/cannot-commit-routes-without-express-app.d.ts +0 -3
@@ -1,37 +1,38 @@
1
- import { Application, Request, RequestHandler, Response, Router } from 'express';
1
+ import Koa from 'koa';
2
+ import KoaRouter from '@koa/router';
2
3
  import PsychicController from '../controller/index.js';
3
4
  import { NamespaceConfig, PsychicControllerActions } from '../router/helpers.js';
4
- import RouteManager from './route-manager.js';
5
+ import RouteManager, { KoaMiddleware } from './route-manager.js';
5
6
  import { HttpMethod, ResourcesOptions } from './types.js';
6
7
  export default class PsychicRouter {
7
- app: Application | null;
8
+ app: Koa | null;
8
9
  currentNamespaces: NamespaceConfig[];
9
10
  routeManager: RouteManager;
10
- constructor(app: Application | null);
11
+ constructor(app: Koa | null);
11
12
  get routes(): import("./route-manager.js").RouteConfig[];
12
13
  private get currentNamespacePaths();
13
14
  commit(): void;
14
15
  get(path: string): void;
15
- get(path: string, middleware: RequestHandler | RequestHandler[]): void;
16
+ get(path: string, middleware: KoaMiddleware | KoaMiddleware[]): void;
16
17
  get<T extends typeof PsychicController>(path: string, controller: T, action: PsychicControllerActions<T>): void;
17
18
  post(path: string): void;
18
- post(path: string, middleware: RequestHandler | RequestHandler[]): void;
19
+ post(path: string, middleware: KoaMiddleware | KoaMiddleware[]): void;
19
20
  post<T extends typeof PsychicController>(path: string, controller: T, action: PsychicControllerActions<T>): void;
20
21
  put(path: string): void;
21
- put(path: string, middleware: RequestHandler | RequestHandler[]): void;
22
+ put(path: string, middleware: KoaMiddleware | KoaMiddleware[]): void;
22
23
  put<T extends typeof PsychicController>(path: string, controller: T, action: PsychicControllerActions<T>): void;
23
24
  patch(path: string): void;
24
- patch(path: string, middleware: RequestHandler | RequestHandler[]): void;
25
+ patch(path: string, middleware: KoaMiddleware | KoaMiddleware[]): void;
25
26
  patch<T extends typeof PsychicController>(path: string, controller: T, action: PsychicControllerActions<T>): void;
26
27
  delete(path: string): void;
27
- delete(path: string, middleware: RequestHandler | RequestHandler[]): void;
28
+ delete(path: string, middleware: KoaMiddleware | KoaMiddleware[]): void;
28
29
  delete<T extends typeof PsychicController>(path: string, controller: T, action: PsychicControllerActions<T>): void;
29
30
  options(path: string): void;
30
- options(path: string, middleware: RequestHandler | RequestHandler[]): void;
31
+ options(path: string, middleware: KoaMiddleware | KoaMiddleware[]): void;
31
32
  options<T extends typeof PsychicController>(path: string, controller: T, action: PsychicControllerActions<T>): void;
32
33
  private prefixPathWithNamespaces;
33
34
  crud(httpMethod: HttpMethod, path: string): void;
34
- crud(httpMethod: HttpMethod, path: string, middleware: RequestHandler | RequestHandler[]): void;
35
+ crud(httpMethod: HttpMethod, path: string, middleware: KoaMiddleware | KoaMiddleware[]): void;
35
36
  crud(httpMethod: HttpMethod, path: string, controller: typeof PsychicController, action: string): void;
36
37
  private checkPathForInvalidChars;
37
38
  namespace(namespace: string, cb: (router: PsychicNestedRouter) => void): void;
@@ -62,15 +63,14 @@ export default class PsychicRouter {
62
63
  * By default, do not provide an attacker with any visibility into which layer
63
64
  * of the application rejected their request.
64
65
  */
65
- handle(controller: typeof PsychicController, action: string, { req, res, }: {
66
- req: Request;
67
- res: Response;
66
+ handle(controller: typeof PsychicController, action: string, { ctx, }: {
67
+ ctx: Koa.Context;
68
68
  }): Promise<void>;
69
- _initializeController(ControllerClass: typeof PsychicController, req: Request, res: Response, action: string): PsychicController;
69
+ _initializeController(ControllerClass: typeof PsychicController, ctx: Koa.Context, action: string): PsychicController;
70
70
  }
71
71
  export declare class PsychicNestedRouter extends PsychicRouter {
72
- router: Router;
73
- constructor(expressApp: Application | null, routeManager: RouteManager, { namespaces, }?: {
72
+ router: KoaRouter;
73
+ constructor(koaApp: Koa | null, routeManager: RouteManager, { namespaces, }?: {
74
74
  namespaces?: NamespaceConfig[];
75
75
  });
76
76
  }
@@ -1,6 +1,7 @@
1
- import { RequestHandler } from 'express';
1
+ import Koa from 'koa';
2
2
  import PsychicController from '../controller/index.js';
3
3
  import { HttpMethod } from './types.js';
4
+ export type KoaMiddleware = Koa.Middleware;
4
5
  export default class RouteManager {
5
6
  routes: RouteConfig[];
6
7
  addRoute({ httpMethod, path, controller, action, }: {
@@ -12,7 +13,7 @@ export default class RouteManager {
12
13
  addMiddleware({ httpMethod, path, middleware, }: {
13
14
  httpMethod: HttpMethod;
14
15
  path: string;
15
- middleware: RequestHandler | RequestHandler[];
16
+ middleware: KoaMiddleware | KoaMiddleware[];
16
17
  }): void;
17
18
  }
18
19
  export type RouteConfig = ControllerActionRouteConfig | MiddlewareRouteConfig;
@@ -25,6 +26,6 @@ export type ControllerActionRouteConfig = BaseRouteConfig & {
25
26
  action: string;
26
27
  };
27
28
  export type MiddlewareRouteConfig = BaseRouteConfig & {
28
- middleware: RequestHandler | RequestHandler[];
29
+ middleware: KoaMiddleware | KoaMiddleware[];
29
30
  };
30
31
  export {};
@@ -1,12 +1,12 @@
1
- import { Express } from 'express';
1
+ import Koa from 'koa';
2
2
  import * as http from 'node:http';
3
3
  import { Server } from 'node:http';
4
4
  import * as https from 'node:https';
5
5
  import { PsychicSslCredentials } from '../../psychic-app/index.js';
6
6
  export interface StartPsychicServerOptions {
7
- app: Express;
7
+ app: Koa;
8
8
  port: number;
9
9
  sslCredentials: PsychicSslCredentials | undefined;
10
10
  }
11
11
  export default function startPsychicServer({ app, port, sslCredentials, }: StartPsychicServerOptions): Promise<Server>;
12
- export declare function createPsychicHttpInstance(app: Express, sslCredentials: PsychicSslCredentials | undefined): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
12
+ export declare function createPsychicHttpInstance(app: Koa, sslCredentials: PsychicSslCredentials | undefined): http.Server<typeof http.IncomingMessage, typeof http.ServerResponse> | https.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
@@ -1,11 +1,11 @@
1
- import { Express } from 'express';
1
+ import Koa from 'koa';
2
2
  import { Server } from 'node:http';
3
3
  import { PsychicSslCredentials } from '../psychic-app/index.js';
4
4
  import { StartPsychicServerOptions } from './helpers/startPsychicServer.js';
5
5
  export default class PsychicServer {
6
6
  static startPsychicServer(opts: StartPsychicServerOptions): Promise<Server>;
7
- static createPsychicHttpInstance(app: Express, sslCredentials: PsychicSslCredentials | undefined): Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> | import("https").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
8
- expressApp: Express;
7
+ static createPsychicHttpInstance(app: Koa, sslCredentials: PsychicSslCredentials | undefined): Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse> | import("https").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
8
+ koaApp: Koa;
9
9
  httpServer: Server;
10
10
  private booted;
11
11
  constructor();
@@ -1,4 +1,4 @@
1
- import { CalendarDate, DateTime, Dream } from '@rvoh/dream';
1
+ import { CalendarDate, ClockTime, ClockTimeTz, DateTime, Dream } from '@rvoh/dream';
2
2
  import { OpenapiSchemaArray, OpenapiSchemaBody, OpenapiSchemaInteger, OpenapiSchemaNumber, OpenapiSchemaObjectBase, OpenapiSchemaPrimitiveGeneric, OpenapiSchemaPropertiesShorthand, OpenapiSchemaString } from '@rvoh/dream/openapi';
3
3
  import { DreamParamSafeAttributes, DreamParamSafeColumnNames, StrictInterface } from '@rvoh/dream/types';
4
4
  import { PsychicParamsDictionary, PsychicParamsPrimitive, PsychicParamsPrimitiveLiteral } from '../controller/index.js';
@@ -62,7 +62,7 @@ export default class Params {
62
62
  }
63
63
  export type ValidatedReturnType<ExpectedType, OptsType> = ExpectedType extends RegExp ? string : ExpectedType extends 'string' ? OptsType extends {
64
64
  enum: infer EnumValue;
65
- } ? EnumValue extends readonly string[] ? EnumValue[number] : never : string : ExpectedType extends 'number' ? number : ExpectedType extends 'datetime' ? DateTime : ExpectedType extends 'date' ? CalendarDate : ExpectedType extends 'bigint' ? string : ExpectedType extends 'integer' ? number : ExpectedType extends 'json' ? object : ExpectedType extends 'boolean' ? boolean : ExpectedType extends 'null' ? null : ExpectedType extends 'uuid' ? string : ExpectedType extends 'datetime[]' ? DateTime[] : ExpectedType extends 'date[]' ? CalendarDate[] : ExpectedType extends 'string[]' ? OptsType extends {
65
+ } ? EnumValue extends readonly string[] ? EnumValue[number] : never : string : ExpectedType extends 'number' ? number : ExpectedType extends 'datetime' ? DateTime : ExpectedType extends 'date' ? CalendarDate : ExpectedType extends 'time' ? ClockTime : ExpectedType extends 'timetz' ? ClockTimeTz : ExpectedType extends 'bigint' ? string : ExpectedType extends 'integer' ? number : ExpectedType extends 'json' ? object : ExpectedType extends 'boolean' ? boolean : ExpectedType extends 'null' ? null : ExpectedType extends 'uuid' ? string : ExpectedType extends 'datetime[]' ? DateTime[] : ExpectedType extends 'date[]' ? CalendarDate[] : ExpectedType extends 'time[]' ? ClockTime[] : ExpectedType extends 'timetz[]' ? ClockTimeTz[] : ExpectedType extends 'string[]' ? OptsType extends {
66
66
  enum: infer EnumValue;
67
67
  } ? EnumValue extends readonly string[] ? EnumValue[number][] : never : string[] : ExpectedType extends 'bigint[]' ? string[] : ExpectedType extends 'number[]' ? number[] : ExpectedType extends 'integer[]' ? number[] : ExpectedType extends 'boolean[]' ? boolean : ExpectedType extends 'null[]' ? null[] : ExpectedType extends 'uuid[]' ? string[] : OpenapiShapeToInterface<ExpectedType, 0>;
68
68
  type OpenapiShapeToInterface<T, Depth extends number> = Depth extends 30 ? never : T extends OpenapiSchemaObjectBase ? {
@@ -1,12 +1,20 @@
1
- import { CookieOptions, Request, Response } from 'express';
1
+ import Koa from 'koa';
2
2
  import { CustomCookieOptions } from '../psychic-app/index.js';
3
3
  export default class Session {
4
- private req;
5
- private res;
6
- constructor(req: Request, res: Response);
4
+ private ctx;
5
+ constructor(ctx: Koa.Context);
7
6
  getCookie(name: string): unknown;
8
7
  setCookie(name: string, data: string, opts?: CustomSessionCookieOptions): void;
9
8
  clearCookie(name: string): void;
10
9
  daysToMilliseconds(numDays: number): number;
11
10
  }
12
- export type CustomSessionCookieOptions = Omit<CookieOptions, 'maxAge'> & CustomCookieOptions;
11
+ export interface CustomSessionCookieOptions extends CustomCookieOptions {
12
+ secure?: boolean;
13
+ httpOnly?: boolean;
14
+ domain?: string;
15
+ path?: string;
16
+ sameSite?: 'strict' | 'lax' | 'none' | boolean;
17
+ expires?: Date;
18
+ signed?: boolean;
19
+ overwrite?: boolean;
20
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "name": "@rvoh/psychic",
4
4
  "description": "Typescript web framework",
5
- "version": "2.3.8",
5
+ "version": "3.0.0-alpha.1",
6
6
  "author": "RVOHealth",
7
7
  "repository": {
8
8
  "type": "git",
@@ -66,34 +66,41 @@
66
66
  "prepack": "pnpm build"
67
67
  },
68
68
  "dependencies": {
69
- "@types/cookie-parser": "^1.4.8",
70
- "@types/cors": "^2.8.17",
71
69
  "ajv": "^8.17.1",
72
70
  "ajv-formats": "^3.0.1",
73
- "body-parser": "^2.2.1",
74
71
  "commander": "^12.1.0",
75
- "cookie-parser": "^1.4.7",
76
- "cors": "^2.8.5",
77
72
  "dotenv": "^16.4.5",
73
+ "fast-json-stringify": "^6.3.0",
78
74
  "pluralize-esm": "^9.0.5",
79
75
  "yoctocolors": "^2.1.1"
80
76
  },
81
77
  "peerDependencies": {
82
- "@rvoh/dream": "^2.2.0",
83
- "@types/express": "^5.0.1",
78
+ "@koa/cors": "^5.0.0",
79
+ "@koa/router": "^15.3.0",
80
+ "@rvoh/dream": "^2.3.1",
81
+ "@types/koa": "^2.15.0",
82
+ "@types/koa__router": "^12.0.5",
84
83
  "commander": "^12.1.0",
85
- "express": "^5.2.1",
84
+ "koa": "^2.15.3",
85
+ "koa-bodyparser": "^4.4.1",
86
+ "koa-conditional-get": "^3.0.0",
87
+ "koa-etag": "^5.0.0",
86
88
  "openapi-typescript": "^7.8.0"
87
89
  },
88
90
  "devDependencies": {
89
91
  "@eslint/js": "^9.39.1",
90
- "@jest-mock/express": "^3.0.0",
91
- "@rvoh/dream": "^2.2.3",
92
- "@rvoh/dream-spec-helpers": "^2.0.0",
93
- "@rvoh/psychic-spec-helpers": "^2.0.0",
94
- "@types/body-parser": "^1.19.6",
95
- "@types/express": "^5.0.6",
96
- "@types/express-session": "^1.18.2",
92
+ "@koa/cors": "^5.0.0",
93
+ "@koa/router": "^15.3.0",
94
+ "@rvoh/dream": "^2.3.1",
95
+ "@rvoh/dream-spec-helpers": "^2.1.1",
96
+ "@rvoh/psychic-spec-helpers": "^3.0.0-alpha.1",
97
+ "@types/koa": "^2.15.0",
98
+ "@types/koa-bodyparser": "^4.3.12",
99
+ "@types/koa-conditional-get": "^2.0.3",
100
+ "@types/koa-etag": "^3.0.3",
101
+ "@types/koa-passport": "^6.0.3",
102
+ "@types/koa__cors": "^5.0.0",
103
+ "@types/koa__router": "^12.0.5",
97
104
  "@types/node": "^22.17.1",
98
105
  "@types/passport": "^0",
99
106
  "@types/passport-local": "^1",
@@ -102,9 +109,13 @@
102
109
  "@typescript-eslint/parser": "^8.48.1",
103
110
  "@typescript/analyze-trace": "^0.10.1",
104
111
  "eslint": "^9.39.1",
105
- "express": "^5.2.1",
106
- "express-session": "^1.18.2",
107
112
  "jsdom": "^26.1.0",
113
+ "koa": "^2.15.3",
114
+ "koa-bodyparser": "^4.4.1",
115
+ "koa-conditional-get": "^3.0.0",
116
+ "koa-etag": "^4.0.0",
117
+ "koa-passport": "^6.0.0",
118
+ "koa-session": "^7.0.2",
108
119
  "kysely": "^0.28.5",
109
120
  "kysely-codegen": "~0.19.0",
110
121
  "luxon-jest-matchers": "^0.1.14",
@@ -117,7 +128,7 @@
117
128
  "puppeteer": "^24.22.3",
118
129
  "supertest": "^7.1.4",
119
130
  "tslib": "^2.7.0",
120
- "tsx": "^4.19.3",
131
+ "tsx": "^4.21.0",
121
132
  "typedoc": "^0.26.6",
122
133
  "typescript": "^5.5.4",
123
134
  "typescript-eslint": "^8.48.1",
@@ -1,12 +0,0 @@
1
- export default class CannotCommitRoutesWithoutExpressApp extends Error {
2
- get message() {
3
- return `
4
- When instantiating a PsychicRouter, if no express app is provided as the
5
- first argument, you are not able to commit your routes. Make sure
6
- to provide an actual express app before commiting, like so:
7
-
8
- const app = express()
9
- new PsychicRouter(app, ...)
10
- `;
11
- }
12
- }
@@ -1,12 +0,0 @@
1
- export default class CannotCommitRoutesWithoutExpressApp extends Error {
2
- get message() {
3
- return `
4
- When instantiating a PsychicRouter, if no express app is provided as the
5
- first argument, you are not able to commit your routes. Make sure
6
- to provide an actual express app before commiting, like so:
7
-
8
- const app = express()
9
- new PsychicRouter(app, ...)
10
- `;
11
- }
12
- }
@@ -1,3 +0,0 @@
1
- export default class CannotCommitRoutesWithoutExpressApp extends Error {
2
- get message(): string;
3
- }