@rvoh/psychic 0.37.0-beta.4 → 0.37.0-beta.6

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 (22) hide show
  1. package/dist/cjs/src/error/openapi/AttemptedToDeriveDescendentSerializersFromNonSerializer.js +1 -0
  2. package/dist/cjs/src/error/openapi/NonSerializerPassedToSerializerOpenapiRenderer.js +1 -0
  3. package/dist/cjs/src/error/openapi/NonSerializerSerializerOverrideProvided.js +5 -1
  4. package/dist/cjs/src/openapi-renderer/SerializerOpenapiRenderer.js +40 -34
  5. package/dist/cjs/src/openapi-renderer/body-segment.js +52 -15
  6. package/dist/cjs/src/openapi-renderer/endpoint.js +2 -8
  7. package/dist/cjs/src/openapi-renderer/helpers/allSerializersFromHandWrittenOpenapi.js +47 -3
  8. package/dist/cjs/src/openapi-renderer/helpers/allSerializersToRefsInOpenapi.js +68 -6
  9. package/dist/esm/src/error/openapi/AttemptedToDeriveDescendentSerializersFromNonSerializer.js +1 -0
  10. package/dist/esm/src/error/openapi/NonSerializerPassedToSerializerOpenapiRenderer.js +1 -0
  11. package/dist/esm/src/error/openapi/NonSerializerSerializerOverrideProvided.js +5 -1
  12. package/dist/esm/src/openapi-renderer/SerializerOpenapiRenderer.js +40 -34
  13. package/dist/esm/src/openapi-renderer/body-segment.js +51 -14
  14. package/dist/esm/src/openapi-renderer/endpoint.js +9 -15
  15. package/dist/esm/src/openapi-renderer/helpers/allSerializersFromHandWrittenOpenapi.js +47 -3
  16. package/dist/esm/src/openapi-renderer/helpers/allSerializersToRefsInOpenapi.js +68 -6
  17. package/dist/types/src/helpers/typeHelpers.d.ts +2 -0
  18. package/dist/types/src/openapi-renderer/body-segment.d.ts +51 -14
  19. package/dist/types/src/openapi-renderer/endpoint.d.ts +2 -1
  20. package/dist/types/src/openapi-renderer/helpers/allSerializersFromHandWrittenOpenapi.d.ts +39 -0
  21. package/dist/types/src/openapi-renderer/helpers/allSerializersToRefsInOpenapi.d.ts +44 -0
  22. package/package.json +2 -2
@@ -1,23 +1,60 @@
1
1
  import { DreamModelSerializerType, OpenapiSchemaBody, OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes, SimpleObjectSerializerType } from '@rvoh/dream';
2
2
  import { OpenapiEndpointResponse, OpenapiRenderOpts, OpenapiResponses } from './endpoint.js';
3
3
  export interface OpenapiBodySegmentRendererOpts {
4
- openapiName: string;
5
4
  renderOpts: OpenapiRenderOpts;
6
5
  target: OpenapiBodyTarget;
7
6
  }
8
- export default class OpenapiBodySegmentRenderer {
7
+ /**
8
+ * @internal
9
+ *
10
+ * Internal class used to recursively expand OpenAPI shorthand notation into full OpenAPI schema objects.
11
+ *
12
+ * This class handles the transformation of various shorthand formats:
13
+ * - Primitive shorthands like `'string'` → `{ type: 'string' }`
14
+ * - Nullable shorthands like `['string', 'null']` → `{ type: ['string', 'null'] }`
15
+ * - Array shorthands like `'string[]'` → `{ type: 'array', items: { type: 'string' } }`
16
+ * - Nullable array shorthands like `['string[]', 'null']` → `{ type: ['array', 'null'], items: { type: 'string' } }`
17
+ * - Serializer references like `{ $serializer: SomeSerializer }` → `{ $ref: '#/components/schemas/SerializerOpenapiName' }`
18
+ * - Serializable references like `{ $serializable: SomeModel, key: 'summary' }` → resolved serializer reference
19
+ *
20
+ * The class recursively processes nested structures (objects, arrays, unions) and maintains
21
+ * a collection of referenced serializers that need to be included in the final OpenAPI document.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Input shorthand
26
+ * {
27
+ * type: 'object',
28
+ * properties: {
29
+ * name: 'string',
30
+ * tags: 'string[]',
31
+ * user: { $serializer: UserSerializer }
32
+ * }
33
+ * }
34
+ *
35
+ * // Output expanded
36
+ * {
37
+ * type: 'object',
38
+ * properties: {
39
+ * name: { type: 'string' },
40
+ * tags: { type: 'array', items: { type: 'string' } },
41
+ * user: { $ref: '#/components/schemas/UserSerializer' }
42
+ * }
43
+ * }
44
+ * ```
45
+ */
46
+ export default class OpenapiSegmentExpander {
9
47
  private bodySegment;
10
48
  private casing;
11
49
  private suppressResponseEnums;
12
50
  private target;
13
- private openapiName;
14
51
  /**
15
52
  * @internal
16
53
  *
17
- * Used to recursively parse nested object structures
54
+ * Used to recursively expand nested object structures
18
55
  * within nested openapi objects
19
56
  */
20
- constructor(bodySegment: OpenapiBodySegment, { openapiName, renderOpts, target }: OpenapiBodySegmentRendererOpts);
57
+ constructor(bodySegment: OpenapiBodySegment, { renderOpts, target }: OpenapiBodySegmentRendererOpts);
21
58
  /**
22
59
  * returns the shorthanded body segment, rendered
23
60
  * to the appropriate openapi shape
@@ -26,7 +63,7 @@ export default class OpenapiBodySegmentRenderer {
26
63
  /**
27
64
  * @internal
28
65
  *
29
- * Recursively parses nested objects and arrays,
66
+ * Recursively expand nested objects and arrays,
30
67
  * as well as primitive types
31
68
  */
32
69
  recursivelyParseBody(bodySegment: OpenapiBodySegment): ReferencedSerializersAndOpenapiSchemaBody;
@@ -40,50 +77,50 @@ export default class OpenapiBodySegmentRenderer {
40
77
  /**
41
78
  * @internal
42
79
  *
43
- * recursively parses a oneOf statement
80
+ * recursively expands a oneOf statement
44
81
  */
45
82
  private oneOfStatement;
46
83
  /**
47
84
  * @internal
48
85
  *
49
- * recursively parses an anyOf statement
86
+ * recursively expand an anyOf statement
50
87
  */
51
88
  private anyOfStatement;
52
89
  /**
53
90
  * @internal
54
91
  *
55
- * recursively parses an allOf statement
92
+ * recursively expand an allOf statement
56
93
  */
57
94
  private allOfStatement;
58
95
  /**
59
96
  * @internal
60
97
  *
61
- * recursively parses an array statement
98
+ * recursively expand an array statement
62
99
  */
63
100
  private arrayStatement;
64
101
  /**
65
102
  * @internal
66
103
  *
67
- * recursively parses an object statement
104
+ * recursively expand an object statement
68
105
  */
69
106
  private objectStatement;
70
107
  /**
71
108
  * @internal
72
109
  *
73
- * parses either the `properties` or `additionalProperties` values
110
+ * expand either the `properties` or `additionalProperties` values
74
111
  * on an object
75
112
  */
76
113
  private parseObjectPropertyStatement;
77
114
  /**
78
115
  * @internal
79
116
  *
80
- * recursively parses a primitive literal type (i.e. string or boolean[])
117
+ * recursively expand a primitive literal type (i.e. string or boolean[])
81
118
  */
82
119
  private primitiveLiteralStatement;
83
120
  /**
84
121
  * @internal
85
122
  *
86
- * recursively parses a primitive object type (i.e. { type: 'string[]' })
123
+ * recursively expand a primitive object type (i.e. { type: 'string[]' })
87
124
  */
88
125
  private primitiveObjectStatement;
89
126
  private typeIsOpenapiArrayPrimitive;
@@ -1,6 +1,7 @@
1
- import { Dream, DreamOrViewModelClassSerializerArrayKeys, DreamOrViewModelClassSerializerKey, DreamSerializable, DreamSerializableArray, OpenapiAllTypes, OpenapiFormats, OpenapiSchemaArray, OpenapiSchemaBody, OpenapiSchemaBodyShorthand, OpenapiSchemaExpressionAllOf, OpenapiSchemaExpressionAnyOf, OpenapiSchemaExpressionOneOf, OpenapiSchemaExpressionRef, OpenapiSchemaObject, OpenapiSchemaProperties, SerializerCasing, ViewModelClass } from '@rvoh/dream';
1
+ import { Dream, DreamOrViewModelClassSerializerKey, DreamSerializable, DreamSerializableArray, OpenapiAllTypes, OpenapiFormats, OpenapiSchemaArray, OpenapiSchemaBody, OpenapiSchemaBodyShorthand, OpenapiSchemaExpressionAllOf, OpenapiSchemaExpressionAnyOf, OpenapiSchemaExpressionOneOf, OpenapiSchemaExpressionRef, OpenapiSchemaObject, OpenapiSchemaProperties, SerializerCasing, ViewModelClass } from '@rvoh/dream';
2
2
  import PsychicController from '../controller/index.js';
3
3
  import { HttpStatusCode, HttpStatusCodeNumber } from '../error/http/status-codes.js';
4
+ import { DreamOrViewModelClassSerializerArrayKeys } from '../helpers/typeHelpers.js';
4
5
  import { RouteConfig } from '../router/route-manager.js';
5
6
  import { HttpMethod } from '../router/types.js';
6
7
  import { OpenapiBodySegment, ReferencedSerializersAndOpenapiEndpointResponse, SerializerArray } from './body-segment.js';
@@ -1,2 +1,41 @@
1
1
  import { DreamModelSerializerType, OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes, SimpleObjectSerializerType } from '@rvoh/dream';
2
+ /**
3
+ * @internal
4
+ *
5
+ * Recursively scans an OpenAPI schema structure and returns an array of all Serializers referenced within it.
6
+ *
7
+ * This function traverses the provided OpenAPI schema definition looking for `$serializer` properties
8
+ * and collects all unique serializer references found. It performs a deep scan of nested objects and
9
+ * arrays to find all serializer references at any level of nesting.
10
+ *
11
+ * **Important**: This function does _not_ recurse into the OpenAPI schemas generated by the discovered
12
+ * Serializers themselves. It only extracts serializers from the hand-written OpenAPI structure provided
13
+ * as input.
14
+ *
15
+ * @param openapi - The OpenAPI schema definition to scan for serializer references
16
+ * @returns An array of unique serializers found in the schema structure
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const schema = {
21
+ * type: 'object',
22
+ * properties: {
23
+ * user: { $serializer: UserSerializer },
24
+ * posts: {
25
+ * type: 'array',
26
+ * items: { $serializer: PostSerializer }
27
+ * },
28
+ * metadata: {
29
+ * type: 'object',
30
+ * properties: {
31
+ * author: { $serializer: UserSerializer } // Duplicate, will be deduplicated
32
+ * }
33
+ * }
34
+ * }
35
+ * }
36
+ *
37
+ * const serializers = allSerializersFromHandWrittenOpenapi(schema)
38
+ * // Returns: [UserSerializer, PostSerializer]
39
+ * ```
40
+ */
2
41
  export default function allSerializersFromHandWrittenOpenapi(openapi: OpenapiSchemaBodyShorthand | OpenapiShorthandPrimitiveTypes | undefined): (DreamModelSerializerType | SimpleObjectSerializerType)[];
@@ -1,2 +1,46 @@
1
1
  import { OpenapiSchemaBodyShorthand, OpenapiShorthandPrimitiveTypes } from '@rvoh/dream';
2
+ /**
3
+ * @internal
4
+ *
5
+ * Transforms OpenAPI schema definitions by replacing serializer shorthand references with proper `$ref` statements.
6
+ *
7
+ * This function is used by the SerializerOpenapiRenderer to ensure that the schemas it generates from
8
+ * Serializers contain `$ref` statements instead of `$serializer` or `$serializable` statements. This
9
+ * transformation enables consistent ordering of `anyOf` statements since `anyOf` arrays are sorted by
10
+ * the `$ref` value, which follows the pattern `'#/components/schemas/TheSerializerOpenapiName'`.
11
+ *
12
+ * The function recursively traverses the schema and transforms:
13
+ * - `{ $serializer: SomeSerializer }` → `{ $ref: '#/components/schemas/SerializerOpenapiName' }`
14
+ * - `{ $serializable: SomeModel, key: 'summary' }` → `{ $ref: '#/components/schemas/ModelSummarySerializer' }`
15
+ *
16
+ * @param openapi - The OpenAPI schema definition that may contain serializer shorthand references
17
+ * @returns The transformed schema with `$ref` statements replacing serializer shorthands
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const input = {
22
+ * type: 'object',
23
+ * properties: {
24
+ * user: { $serializer: UserSerializer },
25
+ * posts: {
26
+ * type: 'array',
27
+ * items: { $serializer: PostSerializer }
28
+ * }
29
+ * }
30
+ * }
31
+ *
32
+ * const output = allSerializersToRefsInOpenapi(input)
33
+ * // Returns:
34
+ * // {
35
+ * // type: 'object',
36
+ * // properties: {
37
+ * // user: { $ref: '#/components/schemas/UserSerializer' },
38
+ * // posts: {
39
+ * // type: 'array',
40
+ * // items: { $ref: '#/components/schemas/PostSerializer' }
41
+ * // }
42
+ * // }
43
+ * // }
44
+ * ```
45
+ */
2
46
  export default function allSerializersToRefsInOpenapi(openapi: OpenapiSchemaBodyShorthand | OpenapiShorthandPrimitiveTypes | undefined): OpenapiSchemaBodyShorthand;
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": "0.37.0-beta.4",
5
+ "version": "0.37.0-beta.6",
6
6
  "author": "RVOHealth",
7
7
  "repository": {
8
8
  "type": "git",
@@ -58,7 +58,7 @@
58
58
  "devDependencies": {
59
59
  "@eslint/js": "^9.19.0",
60
60
  "@jest-mock/express": "^3.0.0",
61
- "@rvoh/dream": "^0.43.0-beta.6",
61
+ "@rvoh/dream": "^0.43.0-beta.9",
62
62
  "@rvoh/dream-spec-helpers": "^0.2.4",
63
63
  "@rvoh/psychic-spec-helpers": "^0.6.0",
64
64
  "@types/express": "^5.0.1",