@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.
- package/dist/cjs/src/error/openapi/AttemptedToDeriveDescendentSerializersFromNonSerializer.js +1 -0
- package/dist/cjs/src/error/openapi/NonSerializerPassedToSerializerOpenapiRenderer.js +1 -0
- package/dist/cjs/src/error/openapi/NonSerializerSerializerOverrideProvided.js +5 -1
- package/dist/cjs/src/openapi-renderer/SerializerOpenapiRenderer.js +40 -34
- package/dist/cjs/src/openapi-renderer/body-segment.js +52 -15
- package/dist/cjs/src/openapi-renderer/endpoint.js +2 -8
- package/dist/cjs/src/openapi-renderer/helpers/allSerializersFromHandWrittenOpenapi.js +47 -3
- package/dist/cjs/src/openapi-renderer/helpers/allSerializersToRefsInOpenapi.js +68 -6
- package/dist/esm/src/error/openapi/AttemptedToDeriveDescendentSerializersFromNonSerializer.js +1 -0
- package/dist/esm/src/error/openapi/NonSerializerPassedToSerializerOpenapiRenderer.js +1 -0
- package/dist/esm/src/error/openapi/NonSerializerSerializerOverrideProvided.js +5 -1
- package/dist/esm/src/openapi-renderer/SerializerOpenapiRenderer.js +40 -34
- package/dist/esm/src/openapi-renderer/body-segment.js +51 -14
- package/dist/esm/src/openapi-renderer/endpoint.js +9 -15
- package/dist/esm/src/openapi-renderer/helpers/allSerializersFromHandWrittenOpenapi.js +47 -3
- package/dist/esm/src/openapi-renderer/helpers/allSerializersToRefsInOpenapi.js +68 -6
- package/dist/types/src/helpers/typeHelpers.d.ts +2 -0
- package/dist/types/src/openapi-renderer/body-segment.d.ts +51 -14
- package/dist/types/src/openapi-renderer/endpoint.d.ts +2 -1
- package/dist/types/src/openapi-renderer/helpers/allSerializersFromHandWrittenOpenapi.d.ts +39 -0
- package/dist/types/src/openapi-renderer/helpers/allSerializersToRefsInOpenapi.d.ts +44 -0
- 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
|
-
|
|
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
|
|
54
|
+
* Used to recursively expand nested object structures
|
|
18
55
|
* within nested openapi objects
|
|
19
56
|
*/
|
|
20
|
-
constructor(bodySegment: OpenapiBodySegment, {
|
|
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
|
|
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
|
|
80
|
+
* recursively expands a oneOf statement
|
|
44
81
|
*/
|
|
45
82
|
private oneOfStatement;
|
|
46
83
|
/**
|
|
47
84
|
* @internal
|
|
48
85
|
*
|
|
49
|
-
* recursively
|
|
86
|
+
* recursively expand an anyOf statement
|
|
50
87
|
*/
|
|
51
88
|
private anyOfStatement;
|
|
52
89
|
/**
|
|
53
90
|
* @internal
|
|
54
91
|
*
|
|
55
|
-
* recursively
|
|
92
|
+
* recursively expand an allOf statement
|
|
56
93
|
*/
|
|
57
94
|
private allOfStatement;
|
|
58
95
|
/**
|
|
59
96
|
* @internal
|
|
60
97
|
*
|
|
61
|
-
* recursively
|
|
98
|
+
* recursively expand an array statement
|
|
62
99
|
*/
|
|
63
100
|
private arrayStatement;
|
|
64
101
|
/**
|
|
65
102
|
* @internal
|
|
66
103
|
*
|
|
67
|
-
* recursively
|
|
104
|
+
* recursively expand an object statement
|
|
68
105
|
*/
|
|
69
106
|
private objectStatement;
|
|
70
107
|
/**
|
|
71
108
|
* @internal
|
|
72
109
|
*
|
|
73
|
-
*
|
|
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
|
|
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
|
|
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,
|
|
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.
|
|
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.
|
|
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",
|