Skip to content

Commit

Permalink
lint and changeset
Browse files Browse the repository at this point in the history
  • Loading branch information
kerwanp committed Nov 13, 2024
1 parent a08584e commit 7e41240
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 93 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-items-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"openapi-metadata": minor
---

Handle array types and fix ApiProperty decorator type
38 changes: 10 additions & 28 deletions packages/openapi-metadata/src/loaders/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ export const ArrayTypeLoader: TypeLoaderFn = async (context, value) => {

// TODO: Better warn stack trace
if (!itemsSchema) {
context.logger.warn(
"You tried to specify an array type with an item that resolves to undefined.",
);
context.logger.warn("You tried to specify an array type with an item that resolves to undefined.");
return;
}

Expand All @@ -72,32 +70,22 @@ export const ClassTypeLoader: TypeLoaderFn = async (context, value) => {
return { $ref: schemaPath(model) };
}

const schema: SetRequired<OpenAPIV3.SchemaObject, "properties" | "required"> =
{
type: "object",
properties: {},
required: [],
};
const schema: SetRequired<OpenAPIV3.SchemaObject, "properties" | "required"> = {
type: "object",
properties: {},
required: [],
};

const properties = PropertyMetadataStorage.getMetadata(value.prototype);

if (!properties) {
context.logger.warn(
`You tried to use '${model}' as a type but it does not contain any ApiProperty.`,
);
context.logger.warn(`You tried to use '${model}' as a type but it does not contain any ApiProperty.`);
}

context.schemas[model] = schema;

for (const [key, property] of Object.entries(properties)) {
const {
required,
type,
name,
enum: e,
schema: s,
...metadata
} = property as any;
const { required, type, name, enum: e, schema: s, ...metadata } = property as any;
schema.properties[key] = {
...(await loadType(context, property)),
...metadata,
Expand Down Expand Up @@ -137,18 +125,12 @@ export async function loadType(
const thunk = isThunk(options.type);
const value = thunk ? (options.type as Function)(context) : options.type;

for (const loader of [
PrimitiveTypeLoader,
...context.typeLoaders,
ClassTypeLoader,
]) {
for (const loader of [PrimitiveTypeLoader, ...context.typeLoaders, ClassTypeLoader]) {
const result = await loader(context, value, options.type);
if (result) {
return result;
}
}

context.logger.warn(
`You tried to use '${options.type.toString()}' as a type but no loader supports it ${thunk}`,
);
context.logger.warn(`You tried to use '${options.type.toString()}' as a type but no loader supports it ${thunk}`);
}
8 changes: 2 additions & 6 deletions packages/openapi-metadata/src/metadata/property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ import type { OpenAPIV3 } from "openapi-types";
import type { TypeOptions } from "../types.js";
import { createMetadataStorage } from "./factory.js";

export type PropertyMetadata = Omit<
OpenAPIV3.NonArraySchemaObject,
"type" | "enum" | "properties" | "required"
> & {
export type PropertyMetadata = Omit<OpenAPIV3.NonArraySchemaObject, "type" | "enum" | "properties" | "required"> & {
name: string;
required: boolean;
} & TypeOptions;

export const PropertyMetadataKey = Symbol("Property");

export const PropertyMetadataStorage =
createMetadataStorage<Record<string, PropertyMetadata>>(PropertyMetadataKey);
export const PropertyMetadataStorage = createMetadataStorage<Record<string, PropertyMetadata>>(PropertyMetadataKey);
64 changes: 11 additions & 53 deletions packages/openapi-metadata/test/decorators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,15 @@ import {
OperationSecurityMetadataStorage,
PropertyMetadataStorage,
} from "../src/metadata/index.js";
import {
ApiBasicAuth,
ApiBearerAuth,
ApiCookieAuth,
ApiOauth2,
} from "../src/decorators/api-security.js";
import { ApiBasicAuth, ApiBearerAuth, ApiCookieAuth, ApiOauth2 } from "../src/decorators/api-security.js";

test("@ApiOperation", () => {
class MyController {
@ApiOperation({ summary: "Hello", path: "/test", methods: ["get"] })
operation() {}
}

const metadata = OperationMetadataStorage.getMetadata(
MyController.prototype,
"operation",
);
const metadata = OperationMetadataStorage.getMetadata(MyController.prototype, "operation");

expect(metadata).toEqual({
summary: "Hello",
Expand All @@ -55,10 +47,7 @@ test("@ApiBody", () => {
operation() {}
}

const metadata = OperationBodyMetadataStorage.getMetadata(
MyController.prototype,
"operation",
);
const metadata = OperationBodyMetadataStorage.getMetadata(MyController.prototype, "operation");

expect(metadata).toEqual({
type: "string",
Expand All @@ -73,11 +62,7 @@ test("@ApiParam", () => {
operation() {}
}

const metadata = OperationParameterMetadataStorage.getMetadata(
MyController.prototype,
"operation",
true,
);
const metadata = OperationParameterMetadataStorage.getMetadata(MyController.prototype, "operation", true);

expect(metadata).toEqual([
{ in: "path", name: "test" },
Expand All @@ -92,11 +77,7 @@ test("@ApiHeader", () => {
operation() {}
}

const metadata = OperationParameterMetadataStorage.getMetadata(
MyController.prototype,
"operation",
true,
);
const metadata = OperationParameterMetadataStorage.getMetadata(MyController.prototype, "operation", true);

expect(metadata).toEqual([
{ in: "header", name: "test" },
Expand All @@ -111,11 +92,7 @@ test("@ApiCookie", () => {
operation() {}
}

const metadata = OperationParameterMetadataStorage.getMetadata(
MyController.prototype,
"operation",
true,
);
const metadata = OperationParameterMetadataStorage.getMetadata(MyController.prototype, "operation", true);

expect(metadata).toEqual([
{ in: "cookie", name: "test" },
Expand All @@ -130,11 +107,7 @@ test("@ApiQuery", () => {
operation() {}
}

const metadata = OperationParameterMetadataStorage.getMetadata(
MyController.prototype,
"operation",
true,
);
const metadata = OperationParameterMetadataStorage.getMetadata(MyController.prototype, "operation", true);

expect(metadata).toEqual([
{ in: "query", name: "test" },
Expand All @@ -149,11 +122,7 @@ test("@ApiResponse", () => {
operation() {}
}

const metadata = OperationResponseMetadataStorage.getMetadata(
MyController.prototype,
"operation",
true,
);
const metadata = OperationResponseMetadataStorage.getMetadata(MyController.prototype, "operation", true);

expect(metadata).toEqual({
default: { status: "default", mediaType: "text/html", type: "string" },
Expand All @@ -168,11 +137,7 @@ test("@ApiTags", () => {
operation() {}
}

const metadata = OperationMetadataStorage.getMetadata(
MyController.prototype,
"operation",
true,
);
const metadata = OperationMetadataStorage.getMetadata(MyController.prototype, "operation", true);

expect(metadata.tags).toEqual(["Root", "Hello", "World"]);
});
Expand All @@ -187,11 +152,7 @@ test("@ApiSecurity", () => {
operation() {}
}

const metadata = OperationSecurityMetadataStorage.getMetadata(
MyController.prototype,
"operation",
true,
);
const metadata = OperationSecurityMetadataStorage.getMetadata(MyController.prototype, "operation", true);

expect(metadata).toEqual({
custom: [],
Expand All @@ -216,10 +177,7 @@ test("@ApiExcludeOperation", () => {
operation() {}
}

const metadata = ExcludeMetadataStorage.getMetadata(
MyController.prototype,
"operation",
);
const metadata = ExcludeMetadataStorage.getMetadata(MyController.prototype, "operation");
expect(metadata).toBe(true);
});

Expand Down
8 changes: 2 additions & 6 deletions packages/openapi-metadata/test/loaders/array.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,11 @@ test("simple array", async () => {
test("empty array should warn", async () => {
// @ts-expect-error
expect(await ArrayTypeLoader(context, [])).toEqual(undefined);
expect(error).toContain(
"You tried to specify an array type without any item",
);
expect(error).toContain("You tried to specify an array type without any item");
});

test("array with multiple items should warn", async () => {
// @ts-expect-error
expect(await ArrayTypeLoader(context, [String, Number])).toEqual(undefined);
expect(error).toContain(
"You tried to specify an array type with multiple items.",
);
expect(error).toContain("You tried to specify an array type with multiple items.");
});

0 comments on commit 7e41240

Please sign in to comment.