@tsed/platform-response-filter 8.1.0 → 8.3.0

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.
@@ -0,0 +1,2 @@
1
+ export const ANY_CONTENT_TYPE = "*/*";
2
+ //# sourceMappingURL=ANY_CONTENT_TYPE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ANY_CONTENT_TYPE.js","sourceRoot":"","sources":["../../../src/constants/ANY_CONTENT_TYPE.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC"}
package/lib/esm/index.js CHANGED
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * @file Automatically generated by @tsed/barrels.
3
3
  */
4
+ export * from "./constants/ANY_CONTENT_TYPE.js";
4
5
  export * from "./decorators/responseFilter.js";
5
6
  export * from "./domain/ResponseFiltersContainer.js";
6
7
  export * from "./errors/TemplateRenderError.js";
7
8
  export * from "./interfaces/ResponseFilterMethods.js";
9
+ export * from "./services/PlatformContentTypeResolver.js";
10
+ export * from "./services/PlatformContentTypesContainer.js";
8
11
  export * from "./services/PlatformResponseFilter.js";
9
- export * from "./utils/getContentType.js";
10
12
  export * from "./utils/renderView.js";
11
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sCAAsC,CAAC;AACrD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,sCAAsC,CAAC;AACrD,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,sCAAsC,CAAC;AACrD,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { isObject } from "@tsed/core";
2
+ import { inject, injectable } from "@tsed/di";
3
+ import { ANY_CONTENT_TYPE } from "../constants/ANY_CONTENT_TYPE.js";
4
+ import { PLATFORM_CONTENT_TYPES_CONTAINER } from "./PlatformContentTypesContainer.js";
5
+ /**
6
+ * @ignore
7
+ */
8
+ export function getContentType(data, ctx) {
9
+ const { endpoint, response } = ctx;
10
+ const { operation } = endpoint;
11
+ const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
12
+ if (contentType && contentType !== ANY_CONTENT_TYPE) {
13
+ if (contentType === "application/json" && isObject(data)) {
14
+ return "application/json";
15
+ }
16
+ return contentType;
17
+ }
18
+ if (endpoint.view) {
19
+ return "text/html";
20
+ }
21
+ }
22
+ /**
23
+ * @ignore
24
+ */
25
+ function resolver(data, ctx) {
26
+ const contentType = getContentType(data, ctx);
27
+ if (ctx.request.get("Accept")) {
28
+ const { contentTypes } = inject(PLATFORM_CONTENT_TYPES_CONTAINER);
29
+ const bestContentType = ctx.request.accepts([contentType].concat(contentTypes).filter(Boolean));
30
+ if (bestContentType) {
31
+ return [].concat(bestContentType).filter((type) => type !== "*/*")[0];
32
+ }
33
+ }
34
+ return contentType;
35
+ }
36
+ export const PLATFORM_CONTENT_TYPE_RESOLVER = injectable(Symbol.for("PLATFORM_CONTENT_TYPE_RESOLVER"))
37
+ .factory(() => resolver)
38
+ .token();
39
+ //# sourceMappingURL=PlatformContentTypeResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlatformContentTypeResolver.js","sourceRoot":"","sources":["../../../src/services/PlatformContentTypeResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AACpC,OAAO,EAAmB,MAAM,EAAE,UAAU,EAAC,MAAM,UAAU,CAAC;AAE9D,OAAO,EAAC,gBAAgB,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAC,gCAAgC,EAAC,MAAM,oCAAoC,CAAC;AAEpF;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAS,EAAE,GAAgB;IACxD,MAAM,EAAC,QAAQ,EAAE,QAAQ,EAAC,GAAG,GAAG,CAAC;IACjC,MAAM,EAAC,SAAS,EAAC,GAAG,QAAQ,CAAC;IAE7B,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,IAAI,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAEvG,IAAI,WAAW,IAAI,WAAW,KAAK,gBAAgB,EAAE,CAAC;QACpD,IAAI,WAAW,KAAK,kBAAkB,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,OAAO,kBAAkB,CAAC;QAC5B,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,IAAS,EAAE,GAAgB;IAC3C,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE9C,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9B,MAAM,EAAC,YAAY,EAAC,GAAG,MAAM,CAAmC,gCAAgC,CAAC,CAAC;QAElG,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAEhG,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,EAAE,CAAC,MAAM,CAAC,eAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAMD,MAAM,CAAC,MAAM,8BAA8B,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;KACnG,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC;KACvB,KAAK,EAAE,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { constant, inject, injectable } from "@tsed/di";
2
+ import { ANY_CONTENT_TYPE } from "../constants/ANY_CONTENT_TYPE.js";
3
+ import { ResponseFiltersContainer } from "../domain/ResponseFiltersContainer.js";
4
+ function factory() {
5
+ const responseFilters = constant("responseFilters", []);
6
+ const containers = new Map();
7
+ ResponseFiltersContainer.forEach((token, type) => {
8
+ if (responseFilters.includes(token)) {
9
+ containers.set(type, token);
10
+ }
11
+ });
12
+ return {
13
+ contentTypes: [...containers.keys()],
14
+ resolve(bestContentType) {
15
+ const token = containers.get(bestContentType) || containers.get(ANY_CONTENT_TYPE);
16
+ if (token) {
17
+ return inject(token);
18
+ }
19
+ }
20
+ };
21
+ }
22
+ export const PLATFORM_CONTENT_TYPES_CONTAINER = injectable(Symbol.for("PLATFORM_CONTENT_TYPES_CONTAINER")).factory(factory).token();
23
+ //# sourceMappingURL=PlatformContentTypesContainer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlatformContentTypesContainer.js","sourceRoot":"","sources":["../../../src/services/PlatformContentTypesContainer.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAqB,MAAM,UAAU,CAAC;AAE1E,OAAO,EAAC,gBAAgB,EAAC,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAoB,wBAAwB,EAAC,MAAM,uCAAuC,CAAC;AAGlG,SAAS,OAAO;IACd,MAAM,eAAe,GAAG,QAAQ,CAAgC,iBAAiB,EAAE,EAAE,CAAC,CAAC;IACvF,MAAM,UAAU,GAA0C,IAAI,GAAG,EAAE,CAAC;IAEpE,wBAAwB,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC/C,IAAI,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,YAAY,EAAE,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;QACpC,OAAO,CAAC,eAAuB;YAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAElF,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,MAAM,CAAwB,KAAK,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAGD,MAAM,CAAC,MAAM,gCAAgC,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC"}
@@ -1,35 +1,17 @@
1
1
  import { isSerializable } from "@tsed/core";
2
2
  import { constant, inject, injectable } from "@tsed/di";
3
3
  import { serialize } from "@tsed/json-mapper";
4
- import { ResponseFiltersContainer } from "../domain/ResponseFiltersContainer.js";
5
- import { ANY_CONTENT_TYPE, getContentType } from "../utils/getContentType.js";
6
4
  import { renderView } from "../utils/renderView.js";
5
+ import { PLATFORM_CONTENT_TYPE_RESOLVER } from "./PlatformContentTypeResolver.js";
6
+ import { PLATFORM_CONTENT_TYPES_CONTAINER } from "./PlatformContentTypesContainer.js";
7
7
  /**
8
8
  * @platform
9
9
  */
10
10
  export class PlatformResponseFilter {
11
11
  constructor() {
12
- this.types = new Map();
13
- this.responseFilters = constant("responseFilters", []);
14
12
  this.additionalProperties = constant("additionalProperties");
15
- ResponseFiltersContainer.forEach((token, type) => {
16
- if (this.responseFilters.includes(token)) {
17
- this.types.set(type, token);
18
- }
19
- });
20
- }
21
- get contentTypes() {
22
- return [...this.types.keys()];
23
- }
24
- getBestContentType(data, ctx) {
25
- const contentType = getContentType(data, ctx);
26
- if (ctx.request.get("Accept")) {
27
- const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));
28
- if (bestContentType) {
29
- return [].concat(bestContentType).filter((type) => type !== "*/*")[0];
30
- }
31
- }
32
- return contentType;
13
+ this.container = inject(PLATFORM_CONTENT_TYPES_CONTAINER);
14
+ this.contentTypeResolver = inject(PLATFORM_CONTENT_TYPE_RESOLVER);
33
15
  }
34
16
  /**
35
17
  * Call filters to transform data
@@ -39,9 +21,9 @@ export class PlatformResponseFilter {
39
21
  transform(data, ctx) {
40
22
  const { response } = ctx;
41
23
  if (ctx.endpoint?.operation) {
42
- const bestContentType = this.getBestContentType(data, ctx);
24
+ const bestContentType = this.contentTypeResolver(data, ctx);
43
25
  bestContentType && response.contentType(bestContentType);
44
- const resolved = this.resolve(bestContentType);
26
+ const resolved = this.container.resolve(bestContentType);
45
27
  if (resolved) {
46
28
  return resolved.transform(data, ctx);
47
29
  }
@@ -73,12 +55,6 @@ export class PlatformResponseFilter {
73
55
  }
74
56
  return data;
75
57
  }
76
- resolve(bestContentType) {
77
- const token = this.types.get(bestContentType) || this.types.get(ANY_CONTENT_TYPE);
78
- if (token) {
79
- return inject(token);
80
- }
81
- }
82
58
  getIncludes(ctx) {
83
59
  if (ctx.request.query.includes) {
84
60
  return [].concat(ctx.request.query.includes).flatMap((include) => include.split(","));
@@ -1 +1 @@
1
- {"version":3,"file":"PlatformResponseFilter.js","sourceRoot":"","sources":["../../../src/services/PlatformResponseFilter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PlatformResponseFilter.js","sourceRoot":"","sources":["../../../src/services/PlatformResponseFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAc,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAC,MAAM,UAAU,CAAC;AACnE,OAAO,EAAC,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAC,8BAA8B,EAAC,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAC,gCAAgC,EAAC,MAAM,oCAAoC,CAAC;AAEpF;;GAEG;AACH,MAAM,OAAO,sBAAsB;IAAnC;QACY,yBAAoB,GAAG,QAAQ,CAAU,sBAAsB,CAAC,CAAC;QACjE,cAAS,GAAG,MAAM,CAAmC,gCAAgC,CAAC,CAAC;QACvF,wBAAmB,GAAG,MAAM,CAAiC,8BAA8B,CAAC,CAAC;IA4DzG,CAAC;IA1DC;;;;OAIG;IACH,SAAS,CAAC,IAAa,EAAE,GAAgB;QACvC,MAAM,EAAC,QAAQ,EAAC,GAAG,GAAG,CAAC;QAEvB,IAAI,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC;YAC5B,MAAM,eAAe,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAE5D,eAAe,IAAI,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;YAEzD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAEzD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,IAAa,EAAE,GAAgB;QAC7C,MAAM,EAAC,QAAQ,EAAE,QAAQ,EAAC,GAAG,GAAG,CAAC;QAEjC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAClB,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACrC,CAAC;iBAAM,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,kBAAkB,CAAC,QAAQ,CAAC,UAAU,EAAE;oBACpE,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;iBAChC,CAAC,CAAC;gBAEH,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE;oBACrB,QAAQ,EAAE,IAAI;oBACd,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;oBAC/C,GAAG,YAAY;oBACf,QAAQ,EAAE,IAAI;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,WAAW,CAAC,GAAgB;QAClC,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC/B,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAChG,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AAED,UAAU,CAAC,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const ANY_CONTENT_TYPE = "*/*";
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * @file Automatically generated by @tsed/barrels.
3
3
  */
4
+ export * from "./constants/ANY_CONTENT_TYPE.js";
4
5
  export * from "./decorators/responseFilter.js";
5
6
  export * from "./domain/ResponseFiltersContainer.js";
6
7
  export * from "./errors/TemplateRenderError.js";
7
8
  export * from "./interfaces/ResponseFilterMethods.js";
9
+ export * from "./services/PlatformContentTypeResolver.js";
10
+ export * from "./services/PlatformContentTypesContainer.js";
8
11
  export * from "./services/PlatformResponseFilter.js";
9
- export * from "./utils/getContentType.js";
10
12
  export * from "./utils/renderView.js";
@@ -0,0 +1,15 @@
1
+ import { type BaseContext } from "@tsed/di";
2
+ /**
3
+ * @ignore
4
+ */
5
+ export declare function getContentType(data: any, ctx: BaseContext): any;
6
+ /**
7
+ * @ignore
8
+ */
9
+ declare function resolver(data: any, ctx: BaseContext): any;
10
+ /**
11
+ * @ignore
12
+ */
13
+ export type PLATFORM_CONTENT_TYPE_RESOLVER = typeof resolver;
14
+ export declare const PLATFORM_CONTENT_TYPE_RESOLVER: any;
15
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { ResponseFilterMethods } from "../interfaces/ResponseFilterMethods.js";
2
+ declare function factory(): {
3
+ contentTypes: string[];
4
+ resolve(bestContentType: string): ResponseFilterMethods<unknown> | undefined;
5
+ };
6
+ export type PLATFORM_CONTENT_TYPES_CONTAINER = ReturnType<typeof factory>;
7
+ export declare const PLATFORM_CONTENT_TYPES_CONTAINER: any;
8
+ export {};
@@ -1,17 +1,14 @@
1
- import { Type } from "@tsed/core";
2
- import { BaseContext, TokenProvider } from "@tsed/di";
3
- import { ResponseFilterKey } from "../domain/ResponseFiltersContainer.js";
4
- import { ResponseFilterMethods } from "../interfaces/ResponseFilterMethods.js";
1
+ import { BaseContext } from "@tsed/di";
5
2
  /**
6
3
  * @platform
7
4
  */
8
5
  export declare class PlatformResponseFilter {
9
- protected types: Map<ResponseFilterKey, TokenProvider>;
10
- protected responseFilters: Type<ResponseFilterMethods<unknown>>[];
11
6
  protected additionalProperties: boolean | undefined;
12
- constructor();
13
- get contentTypes(): ResponseFilterKey[];
14
- getBestContentType(data: any, ctx: BaseContext): any;
7
+ protected container: {
8
+ contentTypes: string[];
9
+ resolve(bestContentType: string): import("../index.js").ResponseFilterMethods<unknown> | undefined;
10
+ };
11
+ protected contentTypeResolver: (data: any, ctx: BaseContext) => any;
15
12
  /**
16
13
  * Call filters to transform data
17
14
  * @param data
@@ -24,6 +21,5 @@ export declare class PlatformResponseFilter {
24
21
  * @param ctx
25
22
  */
26
23
  serialize(data: unknown, ctx: BaseContext): Promise<unknown>;
27
- private resolve;
28
24
  private getIncludes;
29
25
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tsed/platform-response-filter",
3
3
  "description": "Platform response filter module for Ts.ED Framework",
4
4
  "type": "module",
5
- "version": "8.1.0",
5
+ "version": "8.3.0",
6
6
  "source": "./src/index.ts",
7
7
  "main": "./lib/esm/index.js",
8
8
  "module": "./lib/esm/index.js",
@@ -26,23 +26,23 @@
26
26
  "tslib": "2.7.0"
27
27
  },
28
28
  "devDependencies": {
29
- "@tsed/barrels": "8.1.0",
30
- "@tsed/core": "8.1.0",
31
- "@tsed/di": "8.1.0",
32
- "@tsed/exceptions": "8.1.0",
33
- "@tsed/json-mapper": "8.1.0",
34
- "@tsed/schema": "8.1.0",
35
- "@tsed/typescript": "8.1.0",
29
+ "@tsed/barrels": "8.3.0",
30
+ "@tsed/core": "8.3.0",
31
+ "@tsed/di": "8.3.0",
32
+ "@tsed/exceptions": "8.3.0",
33
+ "@tsed/json-mapper": "8.3.0",
34
+ "@tsed/schema": "8.3.0",
35
+ "@tsed/typescript": "8.3.0",
36
36
  "eslint": "9.12.0",
37
37
  "typescript": "5.4.5",
38
38
  "vitest": "2.1.2"
39
39
  },
40
40
  "peerDependencies": {
41
- "@tsed/core": "8.1.0",
42
- "@tsed/di": "8.1.0",
43
- "@tsed/exceptions": "8.1.0",
44
- "@tsed/json-mapper": "8.1.0",
45
- "@tsed/schema": "8.1.0"
41
+ "@tsed/core": "8.3.0",
42
+ "@tsed/di": "8.3.0",
43
+ "@tsed/exceptions": "8.3.0",
44
+ "@tsed/json-mapper": "8.3.0",
45
+ "@tsed/schema": "8.3.0"
46
46
  },
47
47
  "peerDependenciesMeta": {
48
48
  "@tsed/core": {
package/readme.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p style="text-align: center" align="center">
2
- <a href="https://tsed.io" target="_blank"><img src="https://tsed.io/tsed-og.png" width="200" alt="Ts.ED logo"/></a>
2
+ <a href="https://tsed.io" target="_blank"><img src="https://tsed.devtsed-og.png" width="200" alt="Ts.ED logo"/></a>
3
3
  </p>
4
4
 
5
5
  <div align="center">
@@ -0,0 +1 @@
1
+ export const ANY_CONTENT_TYPE = "*/*";
package/src/index.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * @file Automatically generated by @tsed/barrels.
3
3
  */
4
+ export * from "./constants/ANY_CONTENT_TYPE.js";
4
5
  export * from "./decorators/responseFilter.js";
5
6
  export * from "./domain/ResponseFiltersContainer.js";
6
7
  export * from "./errors/TemplateRenderError.js";
7
8
  export * from "./interfaces/ResponseFilterMethods.js";
9
+ export * from "./services/PlatformContentTypeResolver.js";
10
+ export * from "./services/PlatformContentTypesContainer.js";
8
11
  export * from "./services/PlatformResponseFilter.js";
9
- export * from "./utils/getContentType.js";
10
12
  export * from "./utils/renderView.js";
@@ -1,94 +1,102 @@
1
1
  import {PlatformTest} from "@tsed/platform-http/testing";
2
2
  import {EndpointMetadata, Get, Returns, View} from "@tsed/schema";
3
3
 
4
- import {getContentType} from "./getContentType.js";
4
+ import {PLATFORM_CONTENT_TYPE_RESOLVER} from "./PlatformContentTypeResolver.js";
5
+ import {PLATFORM_CONTENT_TYPES_CONTAINER} from "./PlatformContentTypesContainer.js";
6
+
7
+ async function getTestFixture(contentTypes = ["application/json", "text/html"]) {
8
+ const contentTypeResolver = await PlatformTest.invoke<PLATFORM_CONTENT_TYPE_RESOLVER>(PLATFORM_CONTENT_TYPE_RESOLVER, [
9
+ {
10
+ token: PLATFORM_CONTENT_TYPES_CONTAINER,
11
+ use: {
12
+ contentTypes
13
+ }
14
+ }
15
+ ]);
16
+
17
+ const data = {
18
+ test: "test"
19
+ };
20
+
21
+ const ctx = PlatformTest.createRequestContext();
22
+ return {
23
+ data,
24
+ ctx,
25
+ contentTypeResolver
26
+ };
27
+ }
5
28
 
6
- describe("getContentType", () => {
29
+ describe("PlatformContentTypeResolver", () => {
7
30
  beforeEach(() => PlatformTest.create());
8
31
  afterEach(() => PlatformTest.reset());
9
32
 
10
- it("should return the content type (undefined)", () => {
33
+ it("should return the content type (undefined)", async () => {
11
34
  class TestController {
12
35
  @Get("/")
13
36
  get() {}
14
37
  }
15
38
 
16
- const ctx = PlatformTest.createRequestContext();
39
+ const {contentTypeResolver, ctx, data} = await getTestFixture();
40
+
17
41
  ctx.endpoint = EndpointMetadata.get(TestController, "get");
18
42
 
19
- const result = getContentType(
20
- {
21
- test: "test"
22
- },
23
- ctx
24
- );
43
+ const result = await contentTypeResolver(data, ctx);
25
44
 
26
45
  expect(result).toEqual(undefined);
27
46
  });
28
- it("should return the content type (object - application/json)", () => {
47
+ it("should return the content type (object - application/json)", async () => {
29
48
  class TestController {
30
49
  @Get("/")
31
50
  @(Returns(200).ContentType("application/json"))
32
51
  get() {}
33
52
  }
34
53
 
35
- const ctx = PlatformTest.createRequestContext();
54
+ const {contentTypeResolver, ctx, data} = await getTestFixture();
55
+
36
56
  ctx.endpoint = EndpointMetadata.get(TestController, "get");
37
57
  ctx.response.getRes().statusCode = 200;
58
+
38
59
  vi.spyOn(ctx.response, "getContentType").mockReturnValue("application/json");
39
60
 
40
- const result = getContentType(
41
- {
42
- test: "test"
43
- },
44
- ctx
45
- );
61
+ const result = contentTypeResolver(data, ctx);
46
62
 
47
63
  expect(result).toEqual("application/json");
48
64
  });
49
- it("should return the content type (string - application/json)", () => {
65
+ it("should return the content type (string - application/json)", async () => {
50
66
  class TestController {
51
67
  @Get("/")
52
68
  @(Returns(200).ContentType("application/json"))
53
69
  get() {}
54
70
  }
55
71
 
56
- const ctx = PlatformTest.createRequestContext();
72
+ const {contentTypeResolver, ctx, data} = await getTestFixture();
73
+
57
74
  ctx.endpoint = EndpointMetadata.get(TestController, "get");
58
75
  ctx.response.getRes().statusCode = 200;
59
76
  vi.spyOn(ctx.response, "getContentType").mockReturnValue("application/json");
60
77
 
61
- const result = getContentType(
62
- {
63
- test: "test"
64
- },
65
- ctx
66
- );
78
+ const result = contentTypeResolver(data, ctx);
67
79
 
68
80
  expect(result).toEqual("application/json");
69
81
  });
70
- it("should return the content type (string - text/html)", () => {
82
+ it("should return the content type (string - text/html)", async () => {
71
83
  class TestController {
72
84
  @Get("/")
73
85
  @(Returns(200).ContentType("text/html"))
74
86
  get() {}
75
87
  }
76
88
 
77
- const ctx = PlatformTest.createRequestContext();
89
+ const {contentTypeResolver, ctx, data} = await getTestFixture();
90
+
78
91
  ctx.endpoint = EndpointMetadata.get(TestController, "get");
79
92
  ctx.response.getRes().statusCode = 200;
80
93
  vi.spyOn(ctx.response, "getContentType").mockReturnValue("text/html");
81
94
 
82
- const result = getContentType(
83
- {
84
- test: "test"
85
- },
86
- ctx
87
- );
95
+ const result = contentTypeResolver(data, ctx);
88
96
 
89
97
  expect(result).toEqual("text/html");
90
98
  });
91
- it("should return the content type (string - view)", () => {
99
+ it("should return the content type (string - view)", async () => {
92
100
  class TestController {
93
101
  @Get("/")
94
102
  @Returns(200)
@@ -96,17 +104,13 @@ describe("getContentType", () => {
96
104
  get() {}
97
105
  }
98
106
 
99
- const ctx = PlatformTest.createRequestContext();
107
+ const {contentTypeResolver, ctx, data} = await getTestFixture();
108
+
100
109
  ctx.endpoint = EndpointMetadata.get(TestController, "get");
101
110
  ctx.response.getRes().statusCode = 200;
102
111
  ctx.view = "true";
103
112
 
104
- const result = getContentType(
105
- {
106
- test: "test"
107
- },
108
- ctx
109
- );
113
+ const result = contentTypeResolver(data, ctx);
110
114
 
111
115
  expect(result).toEqual("text/html");
112
116
  });
@@ -0,0 +1,54 @@
1
+ import {isObject} from "@tsed/core";
2
+ import {type BaseContext, inject, injectable} from "@tsed/di";
3
+
4
+ import {ANY_CONTENT_TYPE} from "../constants/ANY_CONTENT_TYPE.js";
5
+ import {PLATFORM_CONTENT_TYPES_CONTAINER} from "./PlatformContentTypesContainer.js";
6
+
7
+ /**
8
+ * @ignore
9
+ */
10
+ export function getContentType(data: any, ctx: BaseContext) {
11
+ const {endpoint, response} = ctx;
12
+ const {operation} = endpoint;
13
+
14
+ const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
15
+
16
+ if (contentType && contentType !== ANY_CONTENT_TYPE) {
17
+ if (contentType === "application/json" && isObject(data)) {
18
+ return "application/json";
19
+ }
20
+
21
+ return contentType;
22
+ }
23
+
24
+ if (endpoint.view) {
25
+ return "text/html";
26
+ }
27
+ }
28
+
29
+ /**
30
+ * @ignore
31
+ */
32
+ function resolver(data: any, ctx: BaseContext) {
33
+ const contentType = getContentType(data, ctx);
34
+
35
+ if (ctx.request.get("Accept")) {
36
+ const {contentTypes} = inject<PLATFORM_CONTENT_TYPES_CONTAINER>(PLATFORM_CONTENT_TYPES_CONTAINER);
37
+
38
+ const bestContentType = ctx.request.accepts([contentType].concat(contentTypes).filter(Boolean));
39
+
40
+ if (bestContentType) {
41
+ return [].concat(bestContentType as any).filter((type) => type !== "*/*")[0];
42
+ }
43
+ }
44
+
45
+ return contentType;
46
+ }
47
+
48
+ /**
49
+ * @ignore
50
+ */
51
+ export type PLATFORM_CONTENT_TYPE_RESOLVER = typeof resolver;
52
+ export const PLATFORM_CONTENT_TYPE_RESOLVER = injectable(Symbol.for("PLATFORM_CONTENT_TYPE_RESOLVER"))
53
+ .factory(() => resolver)
54
+ .token();
@@ -0,0 +1,31 @@
1
+ import type {Type} from "@tsed/core";
2
+ import {constant, inject, injectable, type TokenProvider} from "@tsed/di";
3
+
4
+ import {ANY_CONTENT_TYPE} from "../constants/ANY_CONTENT_TYPE.js";
5
+ import {ResponseFilterKey, ResponseFiltersContainer} from "../domain/ResponseFiltersContainer.js";
6
+ import type {ResponseFilterMethods} from "../interfaces/ResponseFilterMethods.js";
7
+
8
+ function factory() {
9
+ const responseFilters = constant<Type<ResponseFilterMethods>[]>("responseFilters", []);
10
+ const containers: Map<ResponseFilterKey, TokenProvider> = new Map();
11
+
12
+ ResponseFiltersContainer.forEach((token, type) => {
13
+ if (responseFilters.includes(token)) {
14
+ containers.set(type, token);
15
+ }
16
+ });
17
+
18
+ return {
19
+ contentTypes: [...containers.keys()],
20
+ resolve(bestContentType: string) {
21
+ const token = containers.get(bestContentType) || containers.get(ANY_CONTENT_TYPE);
22
+
23
+ if (token) {
24
+ return inject<ResponseFilterMethods>(token);
25
+ }
26
+ }
27
+ };
28
+ }
29
+
30
+ export type PLATFORM_CONTENT_TYPES_CONTAINER = ReturnType<typeof factory>;
31
+ export const PLATFORM_CONTENT_TYPES_CONTAINER = injectable(Symbol.for("PLATFORM_CONTENT_TYPES_CONTAINER")).factory(factory).token();
@@ -1,45 +1,18 @@
1
- import {isSerializable, Type} from "@tsed/core";
2
- import {BaseContext, constant, inject, injectable, TokenProvider} from "@tsed/di";
1
+ import {isSerializable} from "@tsed/core";
2
+ import {BaseContext, constant, inject, injectable} from "@tsed/di";
3
3
  import {serialize} from "@tsed/json-mapper";
4
4
 
5
- import {ResponseFilterKey, ResponseFiltersContainer} from "../domain/ResponseFiltersContainer.js";
6
- import {ResponseFilterMethods} from "../interfaces/ResponseFilterMethods.js";
7
- import {ANY_CONTENT_TYPE, getContentType} from "../utils/getContentType.js";
8
5
  import {renderView} from "../utils/renderView.js";
6
+ import {PLATFORM_CONTENT_TYPE_RESOLVER} from "./PlatformContentTypeResolver.js";
7
+ import {PLATFORM_CONTENT_TYPES_CONTAINER} from "./PlatformContentTypesContainer.js";
9
8
 
10
9
  /**
11
10
  * @platform
12
11
  */
13
12
  export class PlatformResponseFilter {
14
- protected types: Map<ResponseFilterKey, TokenProvider> = new Map();
15
- protected responseFilters = constant<Type<ResponseFilterMethods>[]>("responseFilters", []);
16
13
  protected additionalProperties = constant<boolean>("additionalProperties");
17
-
18
- constructor() {
19
- ResponseFiltersContainer.forEach((token, type) => {
20
- if (this.responseFilters.includes(token)) {
21
- this.types.set(type, token);
22
- }
23
- });
24
- }
25
-
26
- get contentTypes(): ResponseFilterKey[] {
27
- return [...this.types.keys()];
28
- }
29
-
30
- getBestContentType(data: any, ctx: BaseContext) {
31
- const contentType = getContentType(data, ctx);
32
-
33
- if (ctx.request.get("Accept")) {
34
- const bestContentType = ctx.request.accepts([contentType].concat(this.contentTypes).filter(Boolean));
35
-
36
- if (bestContentType) {
37
- return [].concat(bestContentType as any).filter((type) => type !== "*/*")[0];
38
- }
39
- }
40
-
41
- return contentType;
42
- }
14
+ protected container = inject<PLATFORM_CONTENT_TYPES_CONTAINER>(PLATFORM_CONTENT_TYPES_CONTAINER);
15
+ protected contentTypeResolver = inject<PLATFORM_CONTENT_TYPE_RESOLVER>(PLATFORM_CONTENT_TYPE_RESOLVER);
43
16
 
44
17
  /**
45
18
  * Call filters to transform data
@@ -50,11 +23,11 @@ export class PlatformResponseFilter {
50
23
  const {response} = ctx;
51
24
 
52
25
  if (ctx.endpoint?.operation) {
53
- const bestContentType = this.getBestContentType(data, ctx);
26
+ const bestContentType = this.contentTypeResolver(data, ctx);
54
27
 
55
28
  bestContentType && response.contentType(bestContentType);
56
29
 
57
- const resolved = this.resolve(bestContentType);
30
+ const resolved = this.container.resolve(bestContentType);
58
31
 
59
32
  if (resolved) {
60
33
  return resolved.transform(data, ctx);
@@ -92,14 +65,6 @@ export class PlatformResponseFilter {
92
65
  return data;
93
66
  }
94
67
 
95
- private resolve(bestContentType: string) {
96
- const token = this.types.get(bestContentType) || this.types.get(ANY_CONTENT_TYPE);
97
-
98
- if (token) {
99
- return inject<ResponseFilterMethods>(token);
100
- }
101
- }
102
-
103
68
  private getIncludes(ctx: BaseContext) {
104
69
  if (ctx.request.query.includes) {
105
70
  return [].concat(ctx.request.query.includes).flatMap((include: string) => include.split(","));
@@ -1,20 +0,0 @@
1
- import { isObject } from "@tsed/core";
2
- export const ANY_CONTENT_TYPE = "*/*";
3
- /**
4
- * @ignore
5
- */
6
- export function getContentType(data, ctx) {
7
- const { endpoint, response } = ctx;
8
- const { operation } = endpoint;
9
- const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
10
- if (contentType && contentType !== ANY_CONTENT_TYPE) {
11
- if (contentType === "application/json" && isObject(data)) {
12
- return "application/json";
13
- }
14
- return contentType;
15
- }
16
- if (endpoint.view) {
17
- return "text/html";
18
- }
19
- }
20
- //# sourceMappingURL=getContentType.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"getContentType.js","sourceRoot":"","sources":["../../../src/utils/getContentType.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,YAAY,CAAC;AAGpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAEtC;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,IAAS,EAAE,GAAgB;IACxD,MAAM,EAAC,QAAQ,EAAE,QAAQ,EAAC,GAAG,GAAG,CAAC;IACjC,MAAM,EAAC,SAAS,EAAC,GAAG,QAAQ,CAAC;IAE7B,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,EAAE,IAAI,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAEvG,IAAI,WAAW,IAAI,WAAW,KAAK,gBAAgB,EAAE,CAAC;QACpD,IAAI,WAAW,KAAK,kBAAkB,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,OAAO,kBAAkB,CAAC;QAC5B,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,WAAW,CAAC;IACrB,CAAC;AACH,CAAC"}
@@ -1,6 +0,0 @@
1
- import type { BaseContext } from "@tsed/di";
2
- export declare const ANY_CONTENT_TYPE = "*/*";
3
- /**
4
- * @ignore
5
- */
6
- export declare function getContentType(data: any, ctx: BaseContext): any;
@@ -1,26 +0,0 @@
1
- import {isObject} from "@tsed/core";
2
- import type {BaseContext} from "@tsed/di";
3
-
4
- export const ANY_CONTENT_TYPE = "*/*";
5
-
6
- /**
7
- * @ignore
8
- */
9
- export function getContentType(data: any, ctx: BaseContext) {
10
- const {endpoint, response} = ctx;
11
- const {operation} = endpoint;
12
-
13
- const contentType = response.getContentType() || operation.getContentTypeOf(response.statusCode) || "";
14
-
15
- if (contentType && contentType !== ANY_CONTENT_TYPE) {
16
- if (contentType === "application/json" && isObject(data)) {
17
- return "application/json";
18
- }
19
-
20
- return contentType;
21
- }
22
-
23
- if (endpoint.view) {
24
- return "text/html";
25
- }
26
- }