Skip to content

Commit

Permalink
fix(schema): add discriminator.mappings information on generated schema
Browse files Browse the repository at this point in the history
  • Loading branch information
Romakita committed Nov 16, 2024
1 parent 0158fb6 commit 60d0763
Show file tree
Hide file tree
Showing 11 changed files with 406 additions and 215 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ lib-cov

# Coverage directory used by tools like istanbul
coverage

coverage-*
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

Expand Down
14 changes: 11 additions & 3 deletions docs/docs/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -1459,22 +1459,30 @@ Here is an example:
```typescript
import {Discriminator, DiscriminatorKey, DiscriminatorValue, Property, Required, OneOf} from "@tsed/schema";

export enum EventType {
PAGE_VIEW = "page_view",
ACTION = "action",
CLICK_ACTION = "click_action"
}

export class Event {
@DiscriminatorKey() // declare this property as discriminator key
type: string;
type: string; // don't set enum here, DiscriminatorKey will generate the correct values for each sub-models

@Property()
value: string;
}

@DiscriminatorValue("page_view")
@DiscriminatorValue(EventType.PAGE_VIEW)
// or @DiscriminatorValue() value can be inferred by the class name (ex: "page_view")
export class PageView extends Event {
override type = EventType.PAGE_VIEW; // optional

@Required()
url: string;
}

@DiscriminatorValue("action", "click_action")
@DiscriminatorValue(EventType.ACTION, EventType.CLICK_ACTION)
export class Action extends Event {
@Required()
event: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ exports[`Discriminator > os3 > should generate the spec 1`] = `
"application/json": {
"schema": {
"discriminator": {
"mappings": {
"action": "#/components/schemas/Action",
"click_action": "#/components/schemas/Action",
"custom_action": "#/components/schemas/CustomAction",
"page_view": "#/components/schemas/PageView",
},
"propertyName": "type",
},
"oneOf": [
Expand Down Expand Up @@ -167,6 +173,12 @@ exports[`Discriminator > os3 > should generate the spec 1`] = `
"application/json": {
"schema": {
"discriminator": {
"mappings": {
"action": "#/components/schemas/Action",
"click_action": "#/components/schemas/Action",
"custom_action": "#/components/schemas/CustomAction",
"page_view": "#/components/schemas/PageView",
},
"propertyName": "type",
},
"oneOf": [
Expand Down Expand Up @@ -204,6 +216,12 @@ exports[`Discriminator > os3 > should generate the spec 1`] = `
"schema": {
"items": {
"discriminator": {
"mappings": {
"action": "#/components/schemas/Action",
"click_action": "#/components/schemas/Action",
"custom_action": "#/components/schemas/CustomAction",
"page_view": "#/components/schemas/PageView",
},
"propertyName": "type",
},
"oneOf": [
Expand Down Expand Up @@ -234,6 +252,12 @@ exports[`Discriminator > os3 > should generate the spec 1`] = `
"schema": {
"items": {
"discriminator": {
"mappings": {
"action": "#/components/schemas/Action",
"click_action": "#/components/schemas/Action",
"custom_action": "#/components/schemas/CustomAction",
"page_view": "#/components/schemas/PageView",
},
"propertyName": "type",
},
"oneOf": [
Expand Down Expand Up @@ -272,6 +296,12 @@ exports[`Discriminator > os3 > should generate the spec 1`] = `
"application/json": {
"schema": {
"discriminator": {
"mappings": {
"action": "#/components/schemas/ActionPartial",
"click_action": "#/components/schemas/ActionPartial",
"custom_action": "#/components/schemas/CustomActionPartial",
"page_view": "#/components/schemas/PageViewPartial",
},
"propertyName": "type",
},
"oneOf": [
Expand Down Expand Up @@ -299,6 +329,12 @@ exports[`Discriminator > os3 > should generate the spec 1`] = `
"application/json": {
"schema": {
"discriminator": {
"mappings": {
"action": "#/components/schemas/Action",
"click_action": "#/components/schemas/Action",
"custom_action": "#/components/schemas/CustomAction",
"page_view": "#/components/schemas/PageView",
},
"propertyName": "type",
},
"oneOf": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {isString} from "@tsed/core";
import {JsonSchema} from "../../domain/JsonSchema.js";
import type {JsonSchemaOptions} from "../../interfaces/JsonSchemaOptions.js";
import {registerJsonSchemaMapper} from "../../registries/JsonSchemaMapperContainer.js";
import {toRef} from "../../utils/ref.js";

function discriminatorMappingMapper(obj: any, _: JsonSchema, options: JsonSchemaOptions) {
if (obj.discriminator?.mapping) {
const entries = Object.entries<JsonSchema | string>(obj.discriminator.mapping);
const newMapping: Record<string, string> = {};

for (const [key, value] of entries) {
newMapping[key] = isString(value) ? value : toRef(value, null, options).$ref;
}

obj.discriminator.mapping = newMapping;
}

return obj;
}

registerJsonSchemaMapper("discriminatorMapping", discriminatorMappingMapper);
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {JsonSchema} from "../../domain/JsonSchema.js";
import {alterRequiredGroups} from "../../hooks/alterRequiredGroups.js";
import type {JsonSchemaOptions} from "../../interfaces/JsonSchemaOptions.js";
import {registerJsonSchemaMapper} from "../../registries/JsonSchemaMapperContainer.js";
import {createRef, createRefName, toRef} from "../../utils/ref.js";

function mapRequiredProps(obj: any, schema: JsonSchema, options: JsonSchemaOptions = {}) {
const {useAlias} = options;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ function serializeSchema(schema: JsonSchema, options: JsonSchemaOptions) {
obj = execMapper("nullable", [obj, schema], options);
obj = alterOneOf(obj, schema, options);
obj = execMapper("inlineEnums", [obj, schema], options);
obj = execMapper("discriminatorMapping", [obj, schema], options);

return obj;
}
Expand Down
1 change: 1 addition & 0 deletions packages/specs/schema/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from "./default/objectMapper.js";
export * from "./default/ofMapper.js";
export * from "./default/propertiesMapper.js";
export * from "./default/requiredMapper.js";
export * from "./default/discriminatorMappingsMapper.js";
export * from "./default/schemaMapper.js";
export * from "./open-spec/generate.js";
export * from "./open-spec/nullableMapper.js";
Expand Down
13 changes: 12 additions & 1 deletion packages/specs/schema/src/domain/JsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,18 @@ export class JsonSchema extends Map<string, any> implements NestedGenerics {
if (jsonSchema.isDiscriminator) {
const discriminator = jsonSchema.discriminatorAncestor.discriminator();
const {propertyName} = discriminator;
super.set("discriminator", {propertyName});

super.set("discriminator", {
propertyName,
mapping: resolved.reduce((acc, schema: JsonSchema) => {
discriminator.types.get(schema.getTarget())?.forEach((key: string) => {
acc[key] = schema;
});

return acc;
}, {})
});

this.isDiscriminator = true;
this.#discriminator = discriminator;
}
Expand Down
6 changes: 4 additions & 2 deletions packages/specs/schema/src/utils/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ export function createRef(name: string, schema: JsonSchema, options: JsonSchemaO
/**
* @ignore
*/
export function toRef(value: JsonSchema, schema: any, options: JsonSchemaOptions) {
export function toRef(value: JsonSchema, schema: unknown | undefined, options: JsonSchemaOptions) {
const name = createRefName(value.getName(), options);

setValue(options, `components.schemas.${name}`, schema);
if (schema) {
setValue(options, `components.schemas.${name}`, schema);
}

return createRef(name, value, options);
}
Loading

0 comments on commit 60d0763

Please sign in to comment.