@webpieces/http-api 0.2.17 → 0.2.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/http-api",
3
- "version": "0.2.17",
3
+ "version": "0.2.21",
4
4
  "description": "HTTP API decorators for defining REST APIs",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -21,5 +21,7 @@
21
21
  "publishConfig": {
22
22
  "access": "public"
23
23
  },
24
- "dependencies": {}
24
+ "dependencies": {
25
+ "@webpieces/core-util": "0.2.21"
26
+ }
25
27
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ContextReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextReader.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/ContextReader.ts"],"names":[],"mappings":"","sourcesContent":["import { PlatformHeader } from './PlatformHeader';\n\n\n"]}
@@ -0,0 +1,94 @@
1
+ import { PlatformHeader } from './PlatformHeader';
2
+ /**
3
+ * ContextReader - Interface for reading header values from context.
4
+ *
5
+ * Different implementations for different environments:
6
+ * - RequestContextReader: Node.js with AsyncLocalStorage (in @webpieces/http-routing, server-side only)
7
+ * - StaticContextReader: Browser or testing with manual header management (in @webpieces/http-client)
8
+ * - CompositeContextReader: Combines multiple readers with priority (in @webpieces/http-client)
9
+ *
10
+ * This interface is defined in @webpieces/http-api so both http-routing and http-client
11
+ * can use it without creating circular dependencies.
12
+ *
13
+ * This interface is DI-independent so it works in both server (Inversify)
14
+ * and client (Angular, browser) environments.
15
+ */
16
+ export interface ContextReader {
17
+ /**
18
+ * Read the value of a platform header.
19
+ * Returns undefined if header not available.
20
+ *
21
+ * @param header - The platform header to read
22
+ * @returns The header value, or undefined if not present
23
+ */
24
+ read(header: PlatformHeader): string | undefined;
25
+ }
26
+ /**
27
+ * HeaderMethods - Utility class for working with platform headers.
28
+ *
29
+ * This class can be injected in both server (Node.js) and client (Angular/browser) environments.
30
+ * It provides common operations for filtering and processing headers.
31
+ *
32
+ * Pattern: Stateless utility class (pure functions, can be instantiated or injected)
33
+ * - Server: Can inject empty instance, use static-like methods
34
+ * - Client: new HeaderMethods() (no DI needed)
35
+ *
36
+ * Usage:
37
+ * ```typescript
38
+ * // Server-side (ContextFilter)
39
+ * constructor(@inject() headerMethods: HeaderMethods) {
40
+ * const allHeaders = [... flatten from extensions ...];
41
+ * this.transferHeaders = headerMethods.findTransferHeaders(allHeaders);
42
+ * }
43
+ *
44
+ * // Client-side (ClientFactory)
45
+ * const headerMethods = new HeaderMethods();
46
+ * const loggableHeaders = headerMethods.findLoggableHeaders(allHeaders, requestHeaders);
47
+ * ```
48
+ */
49
+ export declare class HeaderMethods {
50
+ /**
51
+ * Filter headers to only those that should be transferred (isWantTransferred=true).
52
+ *
53
+ * @param headers - Array of PlatformHeader definitions
54
+ * @returns Filtered array of headers with isWantTransferred=true
55
+ */
56
+ findTransferHeaders(headers: PlatformHeader[]): PlatformHeader[];
57
+ /**
58
+ * Split headers into secure and public categories.
59
+ *
60
+ * @param headers - Array of PlatformHeader definitions
61
+ * @returns SplitHeaders with secureHeaders (isSecured=true) and publicHeaders (isSecured=false)
62
+ */
63
+ secureHeaders(headers: PlatformHeader[]): PlatformHeader[];
64
+ /**
65
+ * Get all headers that should be logged.
66
+ * All headers are loggable - secure headers will be masked by formatHeadersForLogging.
67
+ *
68
+ * @param headers - Array of PlatformHeader definitions
69
+ * @returns All headers (they're all loggable, just some are masked)
70
+ */
71
+ findLoggableHeaders(headers: PlatformHeader[]): PlatformHeader[];
72
+ buildSecureMapForLogs(platformHeaders: PlatformHeader[], contextReader: ContextReader): Map<string, any>;
73
+ /**
74
+ * Format headers for logging with secure masking.
75
+ * Takes filtered PlatformHeaders and actual header values from request.
76
+ *
77
+ * Masking rules for secure headers (isSecured=true):
78
+ * - Length > 15: Show first 3 and last 3 characters with "..." between
79
+ * - Length 8-15: Show first 2 characters with "..."
80
+ * - Length < 8: Show "<secure key too short to log>"
81
+ *
82
+ * @param loggableHeaders - Filtered PlatformHeaders to log
83
+ * @param headerMap - Map of header name (lowercase) -> array of values from request
84
+ * @returns Record of header name -> masked or full value for logging
85
+ */
86
+ formatHeadersForLogging(loggableHeaders: PlatformHeader[], headerMap: Map<string, string[]>): Record<string, string>;
87
+ /**
88
+ * Mask a secure header value based on its length.
89
+ *
90
+ * @param value - The secure header value to mask
91
+ * @returns Masked value
92
+ */
93
+ private maskSecureValue;
94
+ }
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HeaderMethods = void 0;
4
+ /**
5
+ * HeaderMethods - Utility class for working with platform headers.
6
+ *
7
+ * This class can be injected in both server (Node.js) and client (Angular/browser) environments.
8
+ * It provides common operations for filtering and processing headers.
9
+ *
10
+ * Pattern: Stateless utility class (pure functions, can be instantiated or injected)
11
+ * - Server: Can inject empty instance, use static-like methods
12
+ * - Client: new HeaderMethods() (no DI needed)
13
+ *
14
+ * Usage:
15
+ * ```typescript
16
+ * // Server-side (ContextFilter)
17
+ * constructor(@inject() headerMethods: HeaderMethods) {
18
+ * const allHeaders = [... flatten from extensions ...];
19
+ * this.transferHeaders = headerMethods.findTransferHeaders(allHeaders);
20
+ * }
21
+ *
22
+ * // Client-side (ClientFactory)
23
+ * const headerMethods = new HeaderMethods();
24
+ * const loggableHeaders = headerMethods.findLoggableHeaders(allHeaders, requestHeaders);
25
+ * ```
26
+ */
27
+ class HeaderMethods {
28
+ /**
29
+ * Filter headers to only those that should be transferred (isWantTransferred=true).
30
+ *
31
+ * @param headers - Array of PlatformHeader definitions
32
+ * @returns Filtered array of headers with isWantTransferred=true
33
+ */
34
+ findTransferHeaders(headers) {
35
+ return headers.filter(h => h.isWantTransferred);
36
+ }
37
+ /**
38
+ * Split headers into secure and public categories.
39
+ *
40
+ * @param headers - Array of PlatformHeader definitions
41
+ * @returns SplitHeaders with secureHeaders (isSecured=true) and publicHeaders (isSecured=false)
42
+ */
43
+ secureHeaders(headers) {
44
+ return headers.filter(h => h.isSecured);
45
+ }
46
+ /**
47
+ * Get all headers that should be logged.
48
+ * All headers are loggable - secure headers will be masked by formatHeadersForLogging.
49
+ *
50
+ * @param headers - Array of PlatformHeader definitions
51
+ * @returns All headers (they're all loggable, just some are masked)
52
+ */
53
+ findLoggableHeaders(headers) {
54
+ return headers; // All headers are loggable, secure ones will be masked
55
+ }
56
+ buildSecureMapForLogs(platformHeaders, contextReader) {
57
+ const headers = new Map();
58
+ for (const header of platformHeaders) {
59
+ const value = contextReader.read(header);
60
+ if (value) {
61
+ if (!header.isSecured)
62
+ headers.set(header.headerName, value);
63
+ else
64
+ headers.set(header.headerName, this.maskSecureValue(value));
65
+ }
66
+ }
67
+ return headers;
68
+ }
69
+ /**
70
+ * Format headers for logging with secure masking.
71
+ * Takes filtered PlatformHeaders and actual header values from request.
72
+ *
73
+ * Masking rules for secure headers (isSecured=true):
74
+ * - Length > 15: Show first 3 and last 3 characters with "..." between
75
+ * - Length 8-15: Show first 2 characters with "..."
76
+ * - Length < 8: Show "<secure key too short to log>"
77
+ *
78
+ * @param loggableHeaders - Filtered PlatformHeaders to log
79
+ * @param headerMap - Map of header name (lowercase) -> array of values from request
80
+ * @returns Record of header name -> masked or full value for logging
81
+ */
82
+ formatHeadersForLogging(loggableHeaders, headerMap) {
83
+ const result = {};
84
+ for (const platformHeader of loggableHeaders) {
85
+ // Look for header in the map (case-insensitive)
86
+ const values = headerMap.get(platformHeader.headerName.toLowerCase());
87
+ if (!values || values.length === 0) {
88
+ continue;
89
+ }
90
+ const value = values[0]; // Take first value
91
+ if (platformHeader.isSecured) {
92
+ result[platformHeader.headerName] = this.maskSecureValue(value);
93
+ }
94
+ else {
95
+ result[platformHeader.headerName] = value;
96
+ }
97
+ }
98
+ return result;
99
+ }
100
+ /**
101
+ * Mask a secure header value based on its length.
102
+ *
103
+ * @param value - The secure header value to mask
104
+ * @returns Masked value
105
+ */
106
+ maskSecureValue(value) {
107
+ const len = value.length;
108
+ if (len < 8) {
109
+ return '<secure key too short to log>';
110
+ }
111
+ else if (len <= 15) {
112
+ // 8-15 characters: show first 2 + "..."
113
+ return `${value.substring(0, 2)}...`;
114
+ }
115
+ else {
116
+ // > 15 characters: show first 3 + "..." + last 3
117
+ return `${value.substring(0, 3)}...${value.substring(len - 3)}`;
118
+ }
119
+ }
120
+ }
121
+ exports.HeaderMethods = HeaderMethods;
122
+ //# sourceMappingURL=HeaderMethods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderMethods.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/HeaderMethods.ts"],"names":[],"mappings":";;;AA2BA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAa,aAAa;IACtB;;;;;OAKG;IACH,mBAAmB,CAAC,OAAyB;QACzC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC;IACpD,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,OAAyB;QACnC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;OAMG;IACH,mBAAmB,CAAC,OAAyB;QACzC,OAAO,OAAO,CAAC,CAAC,uDAAuD;IAC3E,CAAC;IAED,qBAAqB,CAAC,eAAiC,EAAE,aAA4B;QACjF,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;QAEvC,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzC,IAAG,KAAK,EAAE,CAAC;gBACP,IAAG,CAAC,MAAM,CAAC,SAAS;oBAChB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;;oBAEtC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;YACpE,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,uBAAuB,CAAC,eAAiC,EAAE,SAAgC;QACvF,MAAM,MAAM,GAA2B,EAAE,CAAC;QAE1C,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;YAC3C,gDAAgD;YAChD,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;YACtE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,SAAS;YACb,CAAC;YAED,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB;YAE5C,IAAI,cAAc,CAAC,SAAS,EAAE,CAAC;gBAC3B,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACJ,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;YAC9C,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACK,eAAe,CAAC,KAAa;QACjC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;QAEzB,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;YACV,OAAO,+BAA+B,CAAC;QAC3C,CAAC;aAAM,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC;YACnB,wCAAwC;YACxC,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;QACzC,CAAC;aAAM,CAAC;YACJ,iDAAiD;YACjD,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;QACpE,CAAC;IACL,CAAC;CACJ;AAtGD,sCAsGC","sourcesContent":["import { PlatformHeader } from './PlatformHeader';\n\n/**\n * ContextReader - Interface for reading header values from context.\n *\n * Different implementations for different environments:\n * - RequestContextReader: Node.js with AsyncLocalStorage (in @webpieces/http-routing, server-side only)\n * - StaticContextReader: Browser or testing with manual header management (in @webpieces/http-client)\n * - CompositeContextReader: Combines multiple readers with priority (in @webpieces/http-client)\n *\n * This interface is defined in @webpieces/http-api so both http-routing and http-client\n * can use it without creating circular dependencies.\n *\n * This interface is DI-independent so it works in both server (Inversify)\n * and client (Angular, browser) environments.\n */\nexport interface ContextReader {\n /**\n * Read the value of a platform header.\n * Returns undefined if header not available.\n *\n * @param header - The platform header to read\n * @returns The header value, or undefined if not present\n */\n read(header: PlatformHeader): string | undefined;\n}\n\n/**\n * HeaderMethods - Utility class for working with platform headers.\n *\n * This class can be injected in both server (Node.js) and client (Angular/browser) environments.\n * It provides common operations for filtering and processing headers.\n *\n * Pattern: Stateless utility class (pure functions, can be instantiated or injected)\n * - Server: Can inject empty instance, use static-like methods\n * - Client: new HeaderMethods() (no DI needed)\n *\n * Usage:\n * ```typescript\n * // Server-side (ContextFilter)\n * constructor(@inject() headerMethods: HeaderMethods) {\n * const allHeaders = [... flatten from extensions ...];\n * this.transferHeaders = headerMethods.findTransferHeaders(allHeaders);\n * }\n *\n * // Client-side (ClientFactory)\n * const headerMethods = new HeaderMethods();\n * const loggableHeaders = headerMethods.findLoggableHeaders(allHeaders, requestHeaders);\n * ```\n */\nexport class HeaderMethods {\n /**\n * Filter headers to only those that should be transferred (isWantTransferred=true).\n *\n * @param headers - Array of PlatformHeader definitions\n * @returns Filtered array of headers with isWantTransferred=true\n */\n findTransferHeaders(headers: PlatformHeader[]): PlatformHeader[] {\n return headers.filter(h => h.isWantTransferred);\n }\n\n /**\n * Split headers into secure and public categories.\n *\n * @param headers - Array of PlatformHeader definitions\n * @returns SplitHeaders with secureHeaders (isSecured=true) and publicHeaders (isSecured=false)\n */\n secureHeaders(headers: PlatformHeader[]): PlatformHeader[] {\n return headers.filter(h => h.isSecured);\n }\n\n /**\n * Get all headers that should be logged.\n * All headers are loggable - secure headers will be masked by formatHeadersForLogging.\n *\n * @param headers - Array of PlatformHeader definitions\n * @returns All headers (they're all loggable, just some are masked)\n */\n findLoggableHeaders(headers: PlatformHeader[]): PlatformHeader[] {\n return headers; // All headers are loggable, secure ones will be masked\n }\n\n buildSecureMapForLogs(platformHeaders: PlatformHeader[], contextReader: ContextReader): Map<string, any> {\n const headers = new Map<string, any>();\n\n for (const header of platformHeaders) {\n const value = contextReader.read(header);\n if(value) {\n if(!header.isSecured)\n headers.set(header.headerName, value);\n else\n headers.set(header.headerName, this.maskSecureValue(value));\n }\n }\n\n return headers;\n }\n\n /**\n * Format headers for logging with secure masking.\n * Takes filtered PlatformHeaders and actual header values from request.\n *\n * Masking rules for secure headers (isSecured=true):\n * - Length > 15: Show first 3 and last 3 characters with \"...\" between\n * - Length 8-15: Show first 2 characters with \"...\"\n * - Length < 8: Show \"<secure key too short to log>\"\n *\n * @param loggableHeaders - Filtered PlatformHeaders to log\n * @param headerMap - Map of header name (lowercase) -> array of values from request\n * @returns Record of header name -> masked or full value for logging\n */\n formatHeadersForLogging(loggableHeaders: PlatformHeader[], headerMap: Map<string, string[]>): Record<string, string> {\n const result: Record<string, string> = {};\n\n for (const platformHeader of loggableHeaders) {\n // Look for header in the map (case-insensitive)\n const values = headerMap.get(platformHeader.headerName.toLowerCase());\n if (!values || values.length === 0) {\n continue;\n }\n\n const value = values[0]; // Take first value\n\n if (platformHeader.isSecured) {\n result[platformHeader.headerName] = this.maskSecureValue(value);\n } else {\n result[platformHeader.headerName] = value;\n }\n }\n\n return result;\n }\n\n /**\n * Mask a secure header value based on its length.\n *\n * @param value - The secure header value to mask\n * @returns Masked value\n */\n private maskSecureValue(value: string): string {\n const len = value.length;\n\n if (len < 8) {\n return '<secure key too short to log>';\n } else if (len <= 15) {\n // 8-15 characters: show first 2 + \"...\"\n return `${value.substring(0, 2)}...`;\n } else {\n // > 15 characters: show first 3 + \"...\" + last 3\n return `${value.substring(0, 3)}...${value.substring(len - 3)}`;\n }\n }\n}\n\n\n"]}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * DI symbols for platform headers system.
3
+ *
4
+ * Uses Symbol.for() to create global symbols that work across module boundaries.
5
+ * This is important for Inversify multiInject pattern where multiple modules
6
+ * bind to the same symbol.
7
+ */
8
+ export declare const HEADER_TYPES: {
9
+ /**
10
+ * Symbol for PlatformHeadersExtension instances.
11
+ * Multiple modules can bind PlatformHeadersExtension instances to this symbol,
12
+ * and consumers can use @multiInject to collect all of them.
13
+ *
14
+ * Pattern: Extension (DI-level) vs Plugin (App-level)
15
+ * - Extensions contribute specific capabilities to framework (headers, converters, etc.)
16
+ * - Plugins provide complete features with modules + routes (Hibernate, Jackson, etc.)
17
+ *
18
+ * Usage:
19
+ * ```typescript
20
+ * // In a module
21
+ * const extension = new PlatformHeadersExtension([header1, header2]);
22
+ * bind<PlatformHeadersExtension>(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(extension);
23
+ *
24
+ * // In a consumer
25
+ * constructor(@multiInject(HEADER_TYPES.PlatformHeadersExtension) extensions: PlatformHeadersExtension[]) {}
26
+ * ```
27
+ */
28
+ PlatformHeadersExtension: symbol;
29
+ };
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HEADER_TYPES = void 0;
4
+ /**
5
+ * DI symbols for platform headers system.
6
+ *
7
+ * Uses Symbol.for() to create global symbols that work across module boundaries.
8
+ * This is important for Inversify multiInject pattern where multiple modules
9
+ * bind to the same symbol.
10
+ */
11
+ exports.HEADER_TYPES = {
12
+ /**
13
+ * Symbol for PlatformHeadersExtension instances.
14
+ * Multiple modules can bind PlatformHeadersExtension instances to this symbol,
15
+ * and consumers can use @multiInject to collect all of them.
16
+ *
17
+ * Pattern: Extension (DI-level) vs Plugin (App-level)
18
+ * - Extensions contribute specific capabilities to framework (headers, converters, etc.)
19
+ * - Plugins provide complete features with modules + routes (Hibernate, Jackson, etc.)
20
+ *
21
+ * Usage:
22
+ * ```typescript
23
+ * // In a module
24
+ * const extension = new PlatformHeadersExtension([header1, header2]);
25
+ * bind<PlatformHeadersExtension>(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(extension);
26
+ *
27
+ * // In a consumer
28
+ * constructor(@multiInject(HEADER_TYPES.PlatformHeadersExtension) extensions: PlatformHeadersExtension[]) {}
29
+ * ```
30
+ */
31
+ PlatformHeadersExtension: Symbol.for('PlatformHeadersExtension'),
32
+ };
33
+ //# sourceMappingURL=HeaderTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderTypes.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/HeaderTypes.ts"],"names":[],"mappings":";;;AAAA;;;;;;GAMG;AACU,QAAA,YAAY,GAAG;IACxB;;;;;;;;;;;;;;;;;;OAkBG;IACH,wBAAwB,EAAE,MAAM,CAAC,GAAG,CAAC,0BAA0B,CAAC;CACnE,CAAC","sourcesContent":["/**\n * DI symbols for platform headers system.\n *\n * Uses Symbol.for() to create global symbols that work across module boundaries.\n * This is important for Inversify multiInject pattern where multiple modules\n * bind to the same symbol.\n */\nexport const HEADER_TYPES = {\n /**\n * Symbol for PlatformHeadersExtension instances.\n * Multiple modules can bind PlatformHeadersExtension instances to this symbol,\n * and consumers can use @multiInject to collect all of them.\n *\n * Pattern: Extension (DI-level) vs Plugin (App-level)\n * - Extensions contribute specific capabilities to framework (headers, converters, etc.)\n * - Plugins provide complete features with modules + routes (Hibernate, Jackson, etc.)\n *\n * Usage:\n * ```typescript\n * // In a module\n * const extension = new PlatformHeadersExtension([header1, header2]);\n * bind<PlatformHeadersExtension>(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(extension);\n *\n * // In a consumer\n * constructor(@multiInject(HEADER_TYPES.PlatformHeadersExtension) extensions: PlatformHeadersExtension[]) {}\n * ```\n */\n PlatformHeadersExtension: Symbol.for('PlatformHeadersExtension'),\n};\n"]}
@@ -0,0 +1,41 @@
1
+ import { RouteMetadata } from "./decorators";
2
+ /**
3
+ * LogApiCall - Generic API call logging utility.
4
+ *
5
+ * Used by both server-side (LogApiFilter) and client-side (ClientFactory) for
6
+ * consistent logging patterns across the framework.
7
+ *
8
+ * Logging format patterns:
9
+ * - [API-{type}-req] ClassName.methodName request={...} headers={...}
10
+ * - [API-{type}-resp-SUCCESS] ClassName.methodName response={...}
11
+ * - [API-{type}-resp-OTHER] ClassName.methodName errorType={...} (user errors)
12
+ * - [API-{type}-resp-FAIL] ClassName.methodName error={...} (server errors)
13
+ */
14
+ export declare class LogApiCall {
15
+ /**
16
+ * Execute an API call with logging around it.
17
+ *
18
+ * @param type - 'SVR' or 'CLIENT'
19
+ * @param meta - Route metadata with controllerClassName and methodName
20
+ * @param requestDto - The request DTO
21
+ * @param headers - Map of header name -> values
22
+ * @param splitHeaders - SplitHeaders with secureHeaders and publicHeaders for masking
23
+ * @param method - The method to execute
24
+ */
25
+ execute(type: string, meta: RouteMetadata, requestDto: any, headers: Map<string, any>, method: (dto: any) => Promise<any>): Promise<any>;
26
+ /**
27
+ * Check if an error is a user error (expected behavior from server perspective).
28
+ * User errors are NOT failures - just users making mistakes or validation issues.
29
+ *
30
+ * User errors (logged as OTHER, no stack trace):
31
+ * - HttpBadRequestError (400)
32
+ * - HttpUnauthorizedError (401)
33
+ * - HttpForbiddenError (403)
34
+ * - HttpNotFoundError (404)
35
+ * - HttpUserError (266)
36
+ *
37
+ * @param error - The error to check
38
+ * @returns true if this is a user error, false for server errors
39
+ */
40
+ static isUserError(error: unknown): boolean;
41
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogApiCall = void 0;
4
+ const errors_1 = require("./errors");
5
+ const core_util_1 = require("@webpieces/core-util");
6
+ /**
7
+ * LogApiCall - Generic API call logging utility.
8
+ *
9
+ * Used by both server-side (LogApiFilter) and client-side (ClientFactory) for
10
+ * consistent logging patterns across the framework.
11
+ *
12
+ * Logging format patterns:
13
+ * - [API-{type}-req] ClassName.methodName request={...} headers={...}
14
+ * - [API-{type}-resp-SUCCESS] ClassName.methodName response={...}
15
+ * - [API-{type}-resp-OTHER] ClassName.methodName errorType={...} (user errors)
16
+ * - [API-{type}-resp-FAIL] ClassName.methodName error={...} (server errors)
17
+ */
18
+ class LogApiCall {
19
+ /**
20
+ * Execute an API call with logging around it.
21
+ *
22
+ * @param type - 'SVR' or 'CLIENT'
23
+ * @param meta - Route metadata with controllerClassName and methodName
24
+ * @param requestDto - The request DTO
25
+ * @param headers - Map of header name -> values
26
+ * @param splitHeaders - SplitHeaders with secureHeaders and publicHeaders for masking
27
+ * @param method - The method to execute
28
+ */
29
+ async execute(type, meta, requestDto, headers, method) {
30
+ // Log request - convert Map to Object for JSON serialization
31
+ const headersObj = Object.fromEntries(headers);
32
+ console.log(`[API-${type}-req] ${meta.controllerClassName}.${meta.methodName} ${meta.path} request=${JSON.stringify(requestDto)} headers=${JSON.stringify(headersObj)}`);
33
+ // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- LogApiCall logs errors before re-throwing to caller
34
+ try {
35
+ const response = await method(requestDto);
36
+ // Log success response
37
+ console.log(`[API-${type}-resp-SUCCESS] ${meta.controllerClassName}.${meta.methodName} response=${JSON.stringify(response)}`);
38
+ return response;
39
+ }
40
+ catch (err) {
41
+ const error = (0, core_util_1.toError)(err);
42
+ const errorType = error.constructor.name;
43
+ const errorMessage = error.message;
44
+ // Log error based on type and re-throw
45
+ if (LogApiCall.isUserError(error)) {
46
+ console.log(`[API-${type}-resp-OTHER] ${meta.controllerClassName}.${meta.methodName} errorType=${errorType}`);
47
+ }
48
+ else {
49
+ console.error(`[API-${type}-resp-FAIL] ${meta.controllerClassName}.${meta.methodName} errorType=${errorType} error=${errorMessage}`);
50
+ }
51
+ throw error;
52
+ }
53
+ }
54
+ /**
55
+ * Check if an error is a user error (expected behavior from server perspective).
56
+ * User errors are NOT failures - just users making mistakes or validation issues.
57
+ *
58
+ * User errors (logged as OTHER, no stack trace):
59
+ * - HttpBadRequestError (400)
60
+ * - HttpUnauthorizedError (401)
61
+ * - HttpForbiddenError (403)
62
+ * - HttpNotFoundError (404)
63
+ * - HttpUserError (266)
64
+ *
65
+ * @param error - The error to check
66
+ * @returns true if this is a user error, false for server errors
67
+ */
68
+ static isUserError(error) {
69
+ return (error instanceof errors_1.HttpBadRequestError ||
70
+ error instanceof errors_1.HttpUnauthorizedError ||
71
+ error instanceof errors_1.HttpForbiddenError ||
72
+ error instanceof errors_1.HttpNotFoundError ||
73
+ error instanceof errors_1.HttpUserError);
74
+ }
75
+ }
76
+ exports.LogApiCall = LogApiCall;
77
+ //# sourceMappingURL=LogApiCall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogApiCall.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/LogApiCall.ts"],"names":[],"mappings":";;;AACA,qCAMkB;AAClB,oDAA6C;AAG7C;;;;;;;;;;;GAWG;AACH,MAAa,UAAU;IAEnB;;;;;;;;;OASG;IACI,KAAK,CAAC,OAAO,CAChB,IAAY,EACZ,IAAmB,EACnB,UAAe,EACf,OAAyB,EACzB,MAAkC;QAElC,6DAA6D;QAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CACP,QAAQ,IAAI,SAAS,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAC9J,CAAC;QAEF,qHAAqH;QACrH,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;YAE1C,uBAAuB;YACvB,OAAO,CAAC,GAAG,CACP,QAAQ,IAAI,kBAAkB,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,UAAU,aAAa,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CACnH,CAAC;YAEF,OAAO,QAAQ,CAAC;QACpB,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,IAAA,mBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC;YACzC,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC;YAEnC,uCAAuC;YACvC,IAAI,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBAChC,OAAO,CAAC,GAAG,CACP,QAAQ,IAAI,gBAAgB,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,UAAU,cAAc,SAAS,EAAE,CACnG,CAAC;YACN,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,KAAK,CACT,QAAQ,IAAI,eAAe,IAAI,CAAC,mBAAmB,IAAI,IAAI,CAAC,UAAU,cAAc,SAAS,UAAU,YAAY,EAAE,CACxH,CAAC;YACN,CAAC;YACD,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,WAAW,CAAC,KAAc;QAC7B,OAAO,CACH,KAAK,YAAY,4BAAmB;YACpC,KAAK,YAAY,8BAAqB;YACtC,KAAK,YAAY,2BAAkB;YACnC,KAAK,YAAY,0BAAiB;YAClC,KAAK,YAAY,sBAAa,CACjC,CAAC;IACN,CAAC;CACJ;AA7ED,gCA6EC","sourcesContent":["import {RouteMetadata} from \"./decorators\";\nimport {\n HttpBadRequestError,\n HttpUnauthorizedError,\n HttpForbiddenError,\n HttpNotFoundError,\n HttpUserError,\n} from './errors';\nimport {toError} from \"@webpieces/core-util\";\n\n\n/**\n * LogApiCall - Generic API call logging utility.\n *\n * Used by both server-side (LogApiFilter) and client-side (ClientFactory) for\n * consistent logging patterns across the framework.\n *\n * Logging format patterns:\n * - [API-{type}-req] ClassName.methodName request={...} headers={...}\n * - [API-{type}-resp-SUCCESS] ClassName.methodName response={...}\n * - [API-{type}-resp-OTHER] ClassName.methodName errorType={...} (user errors)\n * - [API-{type}-resp-FAIL] ClassName.methodName error={...} (server errors)\n */\nexport class LogApiCall {\n\n /**\n * Execute an API call with logging around it.\n *\n * @param type - 'SVR' or 'CLIENT'\n * @param meta - Route metadata with controllerClassName and methodName\n * @param requestDto - The request DTO\n * @param headers - Map of header name -> values\n * @param splitHeaders - SplitHeaders with secureHeaders and publicHeaders for masking\n * @param method - The method to execute\n */\n public async execute(\n type: string,\n meta: RouteMetadata,\n requestDto: any,\n headers: Map<string, any>,\n method: (dto: any) => Promise<any>\n ): Promise<any> {\n // Log request - convert Map to Object for JSON serialization\n const headersObj = Object.fromEntries(headers);\n console.log(\n `[API-${type}-req] ${meta.controllerClassName}.${meta.methodName} ${meta.path} request=${JSON.stringify(requestDto)} headers=${JSON.stringify(headersObj)}`\n );\n\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- LogApiCall logs errors before re-throwing to caller\n try {\n const response = await method(requestDto);\n\n // Log success response\n console.log(\n `[API-${type}-resp-SUCCESS] ${meta.controllerClassName}.${meta.methodName} response=${JSON.stringify(response)}`\n );\n\n return response;\n } catch (err: any) {\n const error = toError(err);\n const errorType = error.constructor.name;\n const errorMessage = error.message;\n\n // Log error based on type and re-throw\n if (LogApiCall.isUserError(error)) {\n console.log(\n `[API-${type}-resp-OTHER] ${meta.controllerClassName}.${meta.methodName} errorType=${errorType}`\n );\n } else {\n console.error(\n `[API-${type}-resp-FAIL] ${meta.controllerClassName}.${meta.methodName} errorType=${errorType} error=${errorMessage}`\n );\n }\n throw error;\n }\n }\n\n /**\n * Check if an error is a user error (expected behavior from server perspective).\n * User errors are NOT failures - just users making mistakes or validation issues.\n *\n * User errors (logged as OTHER, no stack trace):\n * - HttpBadRequestError (400)\n * - HttpUnauthorizedError (401)\n * - HttpForbiddenError (403)\n * - HttpNotFoundError (404)\n * - HttpUserError (266)\n *\n * @param error - The error to check\n * @returns true if this is a user error, false for server errors\n */\n static isUserError(error: unknown): boolean {\n return (\n error instanceof HttpBadRequestError ||\n error instanceof HttpUnauthorizedError ||\n error instanceof HttpForbiddenError ||\n error instanceof HttpNotFoundError ||\n error instanceof HttpUserError\n );\n }\n}\n"]}
@@ -0,0 +1,43 @@
1
+ import { Header } from '@webpieces/core-util';
2
+ /**
3
+ * PlatformHeader - Defines an HTTP header that can be transferred between services.
4
+ *
5
+ * Simplified from Java PlatformHeaders:
6
+ * - Single headerName field (used for both HTTP header and MDC logging key)
7
+ * - No separate getLoggerMDCKey() - just use headerName
8
+ *
9
+ * Implements Header interface from core-util to avoid circular dependencies.
10
+ *
11
+ * Per CLAUDE.md: "All data-only structures MUST be classes, not interfaces."
12
+ * This is a data-only class with no business logic methods.
13
+ */
14
+ export declare class PlatformHeader implements Header {
15
+ /**
16
+ * The HTTP header name (e.g., 'x-request-id', 'x-tenant-id').
17
+ * Also used as the MDC logging key in RequestContext.
18
+ * Case-insensitive per HTTP spec, but stored in canonical form.
19
+ */
20
+ readonly headerName: string;
21
+ /**
22
+ * Whether this header should be transferred from HTTP request to RequestContext.
23
+ * If false, header is defined but not automatically transferred.
24
+ * Only headers with isWantTransferred=true are copied from incoming requests.
25
+ */
26
+ readonly isWantTransferred: boolean;
27
+ /**
28
+ * Whether this header contains sensitive data that should be secured/masked in logs.
29
+ * Examples: Authorization tokens, passwords, API keys.
30
+ */
31
+ readonly isSecured: boolean;
32
+ /**
33
+ * Whether this header should be used as a dimension for metrics/monitoring.
34
+ * Examples: x-tenant-id, x-request-id (for distributed tracing).
35
+ */
36
+ readonly isDimensionForMetrics: boolean;
37
+ constructor(headerName: string, isWantTransferred?: boolean, isSecured?: boolean, isDimensionForMetrics?: boolean);
38
+ /**
39
+ * Get the header name (implements Header interface).
40
+ * @returns The HTTP header name
41
+ */
42
+ getHeaderName(): string;
43
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PlatformHeader = void 0;
4
+ /**
5
+ * PlatformHeader - Defines an HTTP header that can be transferred between services.
6
+ *
7
+ * Simplified from Java PlatformHeaders:
8
+ * - Single headerName field (used for both HTTP header and MDC logging key)
9
+ * - No separate getLoggerMDCKey() - just use headerName
10
+ *
11
+ * Implements Header interface from core-util to avoid circular dependencies.
12
+ *
13
+ * Per CLAUDE.md: "All data-only structures MUST be classes, not interfaces."
14
+ * This is a data-only class with no business logic methods.
15
+ */
16
+ class PlatformHeader {
17
+ constructor(headerName, isWantTransferred = true, isSecured = false, isDimensionForMetrics = false) {
18
+ this.headerName = headerName;
19
+ this.isWantTransferred = isWantTransferred;
20
+ this.isSecured = isSecured;
21
+ this.isDimensionForMetrics = isDimensionForMetrics;
22
+ }
23
+ /**
24
+ * Get the header name (implements Header interface).
25
+ * @returns The HTTP header name
26
+ */
27
+ getHeaderName() {
28
+ return this.headerName;
29
+ }
30
+ }
31
+ exports.PlatformHeader = PlatformHeader;
32
+ //# sourceMappingURL=PlatformHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlatformHeader.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/PlatformHeader.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;GAWG;AACH,MAAa,cAAc;IA2BvB,YACI,UAAkB,EAClB,oBAA6B,IAAI,EACjC,YAAqB,KAAK,EAC1B,wBAAiC,KAAK;QAEtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;IACvD,CAAC;IAED;;;OAGG;IACH,aAAa;QACT,OAAO,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;CACJ;AA9CD,wCA8CC","sourcesContent":["import { Header } from '@webpieces/core-util';\n\n/**\n * PlatformHeader - Defines an HTTP header that can be transferred between services.\n *\n * Simplified from Java PlatformHeaders:\n * - Single headerName field (used for both HTTP header and MDC logging key)\n * - No separate getLoggerMDCKey() - just use headerName\n *\n * Implements Header interface from core-util to avoid circular dependencies.\n *\n * Per CLAUDE.md: \"All data-only structures MUST be classes, not interfaces.\"\n * This is a data-only class with no business logic methods.\n */\nexport class PlatformHeader implements Header {\n /**\n * The HTTP header name (e.g., 'x-request-id', 'x-tenant-id').\n * Also used as the MDC logging key in RequestContext.\n * Case-insensitive per HTTP spec, but stored in canonical form.\n */\n readonly headerName: string;\n\n /**\n * Whether this header should be transferred from HTTP request to RequestContext.\n * If false, header is defined but not automatically transferred.\n * Only headers with isWantTransferred=true are copied from incoming requests.\n */\n readonly isWantTransferred: boolean;\n\n /**\n * Whether this header contains sensitive data that should be secured/masked in logs.\n * Examples: Authorization tokens, passwords, API keys.\n */\n readonly isSecured: boolean;\n\n /**\n * Whether this header should be used as a dimension for metrics/monitoring.\n * Examples: x-tenant-id, x-request-id (for distributed tracing).\n */\n readonly isDimensionForMetrics: boolean;\n\n constructor(\n headerName: string,\n isWantTransferred: boolean = true,\n isSecured: boolean = false,\n isDimensionForMetrics: boolean = false\n ) {\n this.headerName = headerName;\n this.isWantTransferred = isWantTransferred;\n this.isSecured = isSecured;\n this.isDimensionForMetrics = isDimensionForMetrics;\n }\n\n /**\n * Get the header name (implements Header interface).\n * @returns The HTTP header name\n */\n getHeaderName(): string {\n return this.headerName;\n }\n}\n"]}
@@ -0,0 +1,51 @@
1
+ import { PlatformHeader } from './PlatformHeader';
2
+ /**
3
+ * PlatformHeadersExtension - Extension that contributes platform headers to the framework.
4
+ *
5
+ * This is a DI-level extension (not an app-level Plugin).
6
+ * Multiple modules can bind PlatformHeadersExtension instances, and the framework
7
+ * collects them via Inversify @multiInject.
8
+ *
9
+ * Two-level plugin system:
10
+ * 1. **Extensions** (DI-level): Contribute specific capabilities to framework
11
+ * - Examples: PlatformHeadersExtension, BodyContentExtension, EntityLookupExtension
12
+ * - Pattern: Bound via multiInject, consumed by framework
13
+ * - Java equivalent: Multibinder<AddPlatformHeaders>, Multibinder<BodyContentBinder>
14
+ *
15
+ * 2. **Plugins** (App-level): Provide complete features with modules + routes
16
+ * - Examples: HibernatePlugin, JacksonPlugin, Auth0Plugin
17
+ * - Pattern: Implements getGuiceModules() + getRouteModules()
18
+ * - Java equivalent: Plugin interface with getGuiceModules() + getRouteModules()
19
+ *
20
+ * Usage:
21
+ * ```typescript
22
+ * // In WebpiecesModule
23
+ * const coreExtension = new PlatformHeadersExtension([
24
+ * WebpiecesCoreHeaders.REQUEST_ID,
25
+ * WebpiecesCoreHeaders.CORRELATION_ID,
26
+ * ]);
27
+ * bind(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(coreExtension);
28
+ *
29
+ * // In CompanyModule
30
+ * const companyExtension = new PlatformHeadersExtension([
31
+ * CompanyHeaders.TENANT_ID,
32
+ * CompanyHeaders.API_VERSION,
33
+ * ]);
34
+ * bind(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(companyExtension);
35
+ *
36
+ * // Framework collects all extensions
37
+ * constructor(@multiInject(HEADER_TYPES.PlatformHeadersExtension) extensions: PlatformHeadersExtension[]) {}
38
+ * ```
39
+ */
40
+ export declare class PlatformHeadersExtension {
41
+ /**
42
+ * The set of platform headers contributed by this extension.
43
+ */
44
+ readonly headers: PlatformHeader[];
45
+ constructor(headers: PlatformHeader[]);
46
+ /**
47
+ * Get all headers from this extension.
48
+ * @returns Array of platform headers
49
+ */
50
+ getHeaders(): PlatformHeader[];
51
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PlatformHeadersExtension = void 0;
4
+ /**
5
+ * PlatformHeadersExtension - Extension that contributes platform headers to the framework.
6
+ *
7
+ * This is a DI-level extension (not an app-level Plugin).
8
+ * Multiple modules can bind PlatformHeadersExtension instances, and the framework
9
+ * collects them via Inversify @multiInject.
10
+ *
11
+ * Two-level plugin system:
12
+ * 1. **Extensions** (DI-level): Contribute specific capabilities to framework
13
+ * - Examples: PlatformHeadersExtension, BodyContentExtension, EntityLookupExtension
14
+ * - Pattern: Bound via multiInject, consumed by framework
15
+ * - Java equivalent: Multibinder<AddPlatformHeaders>, Multibinder<BodyContentBinder>
16
+ *
17
+ * 2. **Plugins** (App-level): Provide complete features with modules + routes
18
+ * - Examples: HibernatePlugin, JacksonPlugin, Auth0Plugin
19
+ * - Pattern: Implements getGuiceModules() + getRouteModules()
20
+ * - Java equivalent: Plugin interface with getGuiceModules() + getRouteModules()
21
+ *
22
+ * Usage:
23
+ * ```typescript
24
+ * // In WebpiecesModule
25
+ * const coreExtension = new PlatformHeadersExtension([
26
+ * WebpiecesCoreHeaders.REQUEST_ID,
27
+ * WebpiecesCoreHeaders.CORRELATION_ID,
28
+ * ]);
29
+ * bind(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(coreExtension);
30
+ *
31
+ * // In CompanyModule
32
+ * const companyExtension = new PlatformHeadersExtension([
33
+ * CompanyHeaders.TENANT_ID,
34
+ * CompanyHeaders.API_VERSION,
35
+ * ]);
36
+ * bind(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(companyExtension);
37
+ *
38
+ * // Framework collects all extensions
39
+ * constructor(@multiInject(HEADER_TYPES.PlatformHeadersExtension) extensions: PlatformHeadersExtension[]) {}
40
+ * ```
41
+ */
42
+ class PlatformHeadersExtension {
43
+ constructor(headers) {
44
+ this.headers = headers;
45
+ }
46
+ /**
47
+ * Get all headers from this extension.
48
+ * @returns Array of platform headers
49
+ */
50
+ getHeaders() {
51
+ return this.headers;
52
+ }
53
+ }
54
+ exports.PlatformHeadersExtension = PlatformHeadersExtension;
55
+ //# sourceMappingURL=PlatformHeadersExtension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlatformHeadersExtension.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/PlatformHeadersExtension.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAa,wBAAwB;IAMjC,YAAY,OAAyB;QACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACH,UAAU;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;CACJ;AAjBD,4DAiBC","sourcesContent":["import { PlatformHeader } from './PlatformHeader';\n\n/**\n * PlatformHeadersExtension - Extension that contributes platform headers to the framework.\n *\n * This is a DI-level extension (not an app-level Plugin).\n * Multiple modules can bind PlatformHeadersExtension instances, and the framework\n * collects them via Inversify @multiInject.\n *\n * Two-level plugin system:\n * 1. **Extensions** (DI-level): Contribute specific capabilities to framework\n * - Examples: PlatformHeadersExtension, BodyContentExtension, EntityLookupExtension\n * - Pattern: Bound via multiInject, consumed by framework\n * - Java equivalent: Multibinder<AddPlatformHeaders>, Multibinder<BodyContentBinder>\n *\n * 2. **Plugins** (App-level): Provide complete features with modules + routes\n * - Examples: HibernatePlugin, JacksonPlugin, Auth0Plugin\n * - Pattern: Implements getGuiceModules() + getRouteModules()\n * - Java equivalent: Plugin interface with getGuiceModules() + getRouteModules()\n *\n * Usage:\n * ```typescript\n * // In WebpiecesModule\n * const coreExtension = new PlatformHeadersExtension([\n * WebpiecesCoreHeaders.REQUEST_ID,\n * WebpiecesCoreHeaders.CORRELATION_ID,\n * ]);\n * bind(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(coreExtension);\n *\n * // In CompanyModule\n * const companyExtension = new PlatformHeadersExtension([\n * CompanyHeaders.TENANT_ID,\n * CompanyHeaders.API_VERSION,\n * ]);\n * bind(HEADER_TYPES.PlatformHeadersExtension).toConstantValue(companyExtension);\n *\n * // Framework collects all extensions\n * constructor(@multiInject(HEADER_TYPES.PlatformHeadersExtension) extensions: PlatformHeadersExtension[]) {}\n * ```\n */\nexport class PlatformHeadersExtension {\n /**\n * The set of platform headers contributed by this extension.\n */\n readonly headers: PlatformHeader[];\n\n constructor(headers: PlatformHeader[]) {\n this.headers = headers;\n }\n\n /**\n * Get all headers from this extension.\n * @returns Array of platform headers\n */\n getHeaders(): PlatformHeader[] {\n return this.headers;\n }\n}\n"]}
package/src/index.d.ts CHANGED
@@ -20,3 +20,8 @@ export { ApiInterface, Get, Post, Put, Delete, Patch, Path, getRoutes, isApiInte
20
20
  export { ValidateImplementation } from './validators';
21
21
  export { ProtocolError, HttpError, HttpNotFoundError, EndpointNotFoundError, HttpBadRequestError, HttpUnauthorizedError, HttpForbiddenError, HttpTimeoutError, HttpBadGatewayError, HttpGatewayTimeoutError, HttpInternalServerError, HttpVendorError, HttpUserError, ENTITY_NOT_FOUND, WRONG_LOGIN_TYPE, WRONG_LOGIN, NOT_APPROVED, EMAIL_NOT_CONFIRMED, WRONG_DOMAIN, WRONG_COMPANY, NO_REG_CODE, } from './errors';
22
22
  export { InstantDto, DateDto, TimeDto, DateTimeDto, InstantUtil, DateUtil, TimeUtil, DateTimeUtil, } from './datetime';
23
+ export { PlatformHeader } from './PlatformHeader';
24
+ export { PlatformHeadersExtension } from './PlatformHeadersExtension';
25
+ export { HeaderMethods, ContextReader } from './HeaderMethods';
26
+ export { HEADER_TYPES } from './HeaderTypes';
27
+ export { LogApiCall } from './LogApiCall';
package/src/index.js CHANGED
@@ -18,7 +18,7 @@
18
18
  * ```
19
19
  */
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.DateTimeUtil = exports.TimeUtil = exports.DateUtil = exports.InstantUtil = exports.NO_REG_CODE = exports.WRONG_COMPANY = exports.WRONG_DOMAIN = exports.EMAIL_NOT_CONFIRMED = exports.NOT_APPROVED = exports.WRONG_LOGIN = exports.WRONG_LOGIN_TYPE = exports.ENTITY_NOT_FOUND = exports.HttpUserError = exports.HttpVendorError = exports.HttpInternalServerError = exports.HttpGatewayTimeoutError = exports.HttpBadGatewayError = exports.HttpTimeoutError = exports.HttpForbiddenError = exports.HttpUnauthorizedError = exports.HttpBadRequestError = exports.EndpointNotFoundError = exports.HttpNotFoundError = exports.HttpError = exports.ProtocolError = exports.METADATA_KEYS = exports.RouteMetadata = exports.isApiInterface = exports.getRoutes = exports.Path = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.ApiInterface = void 0;
21
+ exports.LogApiCall = exports.HEADER_TYPES = exports.HeaderMethods = exports.PlatformHeadersExtension = exports.PlatformHeader = exports.DateTimeUtil = exports.TimeUtil = exports.DateUtil = exports.InstantUtil = exports.NO_REG_CODE = exports.WRONG_COMPANY = exports.WRONG_DOMAIN = exports.EMAIL_NOT_CONFIRMED = exports.NOT_APPROVED = exports.WRONG_LOGIN = exports.WRONG_LOGIN_TYPE = exports.ENTITY_NOT_FOUND = exports.HttpUserError = exports.HttpVendorError = exports.HttpInternalServerError = exports.HttpGatewayTimeoutError = exports.HttpBadGatewayError = exports.HttpTimeoutError = exports.HttpForbiddenError = exports.HttpUnauthorizedError = exports.HttpBadRequestError = exports.EndpointNotFoundError = exports.HttpNotFoundError = exports.HttpError = exports.ProtocolError = exports.METADATA_KEYS = exports.RouteMetadata = exports.isApiInterface = exports.getRoutes = exports.Path = exports.Patch = exports.Delete = exports.Put = exports.Post = exports.Get = exports.ApiInterface = void 0;
22
22
  // API definition decorators
23
23
  var decorators_1 = require("./decorators");
24
24
  Object.defineProperty(exports, "ApiInterface", { enumerable: true, get: function () { return decorators_1.ApiInterface; } });
@@ -62,4 +62,16 @@ Object.defineProperty(exports, "InstantUtil", { enumerable: true, get: function
62
62
  Object.defineProperty(exports, "DateUtil", { enumerable: true, get: function () { return datetime_1.DateUtil; } });
63
63
  Object.defineProperty(exports, "TimeUtil", { enumerable: true, get: function () { return datetime_1.TimeUtil; } });
64
64
  Object.defineProperty(exports, "DateTimeUtil", { enumerable: true, get: function () { return datetime_1.DateTimeUtil; } });
65
+ // Platform Headers
66
+ var PlatformHeader_1 = require("./PlatformHeader");
67
+ Object.defineProperty(exports, "PlatformHeader", { enumerable: true, get: function () { return PlatformHeader_1.PlatformHeader; } });
68
+ var PlatformHeadersExtension_1 = require("./PlatformHeadersExtension");
69
+ Object.defineProperty(exports, "PlatformHeadersExtension", { enumerable: true, get: function () { return PlatformHeadersExtension_1.PlatformHeadersExtension; } });
70
+ var HeaderMethods_1 = require("./HeaderMethods");
71
+ Object.defineProperty(exports, "HeaderMethods", { enumerable: true, get: function () { return HeaderMethods_1.HeaderMethods; } });
72
+ var HeaderTypes_1 = require("./HeaderTypes");
73
+ Object.defineProperty(exports, "HEADER_TYPES", { enumerable: true, get: function () { return HeaderTypes_1.HEADER_TYPES; } });
74
+ // Logging
75
+ var LogApiCall_1 = require("./LogApiCall");
76
+ Object.defineProperty(exports, "LogApiCall", { enumerable: true, get: function () { return LogApiCall_1.LogApiCall; } });
65
77
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAEH,4BAA4B;AAC5B,2CAYsB;AAXlB,0GAAA,YAAY,OAAA;AACZ,iGAAA,GAAG,OAAA;AACH,kGAAA,IAAI,OAAA;AACJ,iGAAA,GAAG,OAAA;AACH,oGAAA,MAAM,OAAA;AACN,mGAAA,KAAK,OAAA;AACL,kGAAA,IAAI,OAAA;AACJ,uGAAA,SAAS,OAAA;AACT,4GAAA,cAAc,OAAA;AACd,2GAAA,aAAa,OAAA;AACb,2GAAA,aAAa,OAAA;AAMjB,cAAc;AACd,mCAuBkB;AAtBd,uGAAA,aAAa,OAAA;AACb,mGAAA,SAAS,OAAA;AACT,2GAAA,iBAAiB,OAAA;AACjB,+GAAA,qBAAqB,OAAA;AACrB,6GAAA,mBAAmB,OAAA;AACnB,+GAAA,qBAAqB,OAAA;AACrB,4GAAA,kBAAkB,OAAA;AAClB,0GAAA,gBAAgB,OAAA;AAChB,6GAAA,mBAAmB,OAAA;AACnB,iHAAA,uBAAuB,OAAA;AACvB,iHAAA,uBAAuB,OAAA;AACvB,yGAAA,eAAe,OAAA;AACf,uGAAA,aAAa,OAAA;AACb,0BAA0B;AAC1B,0GAAA,gBAAgB,OAAA;AAChB,0GAAA,gBAAgB,OAAA;AAChB,qGAAA,WAAW,OAAA;AACX,sGAAA,YAAY,OAAA;AACZ,6GAAA,mBAAmB,OAAA;AACnB,sGAAA,YAAY,OAAA;AACZ,uGAAA,aAAa,OAAA;AACb,qGAAA,WAAW,OAAA;AAGf,iEAAiE;AACjE,uCASoB;AAJhB,uGAAA,WAAW,OAAA;AACX,oGAAA,QAAQ,OAAA;AACR,oGAAA,QAAQ,OAAA;AACR,wGAAA,YAAY,OAAA","sourcesContent":["/**\n * @webpieces/http-api\n *\n * Core HTTP API definition package.\n * Contains decorators and utilities for defining HTTP APIs.\n *\n * This package is used by:\n * - @webpieces/http-routing (server-side): Routes HTTP requests to controllers\n * - @webpieces/http-client (client-side): Generates HTTP clients from API definitions\n *\n * Architecture:\n * ```\n * http-api (defines the contract)\n * ↑\n * ├── http-routing (server: contract → handlers)\n * └── http-client (client: contract → HTTP requests)\n * ```\n */\n\n// API definition decorators\nexport {\n ApiInterface,\n Get,\n Post,\n Put,\n Delete,\n Patch,\n Path,\n getRoutes,\n isApiInterface,\n RouteMetadata,\n METADATA_KEYS,\n} from './decorators';\n\n// Type validators\nexport { ValidateImplementation } from './validators';\n\n// HTTP errors\nexport {\n ProtocolError,\n HttpError,\n HttpNotFoundError,\n EndpointNotFoundError,\n HttpBadRequestError,\n HttpUnauthorizedError,\n HttpForbiddenError,\n HttpTimeoutError,\n HttpBadGatewayError,\n HttpGatewayTimeoutError,\n HttpInternalServerError,\n HttpVendorError,\n HttpUserError,\n // Error subtype constants\n ENTITY_NOT_FOUND,\n WRONG_LOGIN_TYPE,\n WRONG_LOGIN,\n NOT_APPROVED,\n EMAIL_NOT_CONFIRMED,\n WRONG_DOMAIN,\n WRONG_COMPANY,\n NO_REG_CODE,\n} from './errors';\n\n// Date/Time DTOs and Utilities (inspired by Java Time / JSR-310)\nexport {\n InstantDto,\n DateDto,\n TimeDto,\n DateTimeDto,\n InstantUtil,\n DateUtil,\n TimeUtil,\n DateTimeUtil,\n} from './datetime';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/http/http-api/src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;AAEH,4BAA4B;AAC5B,2CAYsB;AAXlB,0GAAA,YAAY,OAAA;AACZ,iGAAA,GAAG,OAAA;AACH,kGAAA,IAAI,OAAA;AACJ,iGAAA,GAAG,OAAA;AACH,oGAAA,MAAM,OAAA;AACN,mGAAA,KAAK,OAAA;AACL,kGAAA,IAAI,OAAA;AACJ,uGAAA,SAAS,OAAA;AACT,4GAAA,cAAc,OAAA;AACd,2GAAA,aAAa,OAAA;AACb,2GAAA,aAAa,OAAA;AAMjB,cAAc;AACd,mCAuBkB;AAtBd,uGAAA,aAAa,OAAA;AACb,mGAAA,SAAS,OAAA;AACT,2GAAA,iBAAiB,OAAA;AACjB,+GAAA,qBAAqB,OAAA;AACrB,6GAAA,mBAAmB,OAAA;AACnB,+GAAA,qBAAqB,OAAA;AACrB,4GAAA,kBAAkB,OAAA;AAClB,0GAAA,gBAAgB,OAAA;AAChB,6GAAA,mBAAmB,OAAA;AACnB,iHAAA,uBAAuB,OAAA;AACvB,iHAAA,uBAAuB,OAAA;AACvB,yGAAA,eAAe,OAAA;AACf,uGAAA,aAAa,OAAA;AACb,0BAA0B;AAC1B,0GAAA,gBAAgB,OAAA;AAChB,0GAAA,gBAAgB,OAAA;AAChB,qGAAA,WAAW,OAAA;AACX,sGAAA,YAAY,OAAA;AACZ,6GAAA,mBAAmB,OAAA;AACnB,sGAAA,YAAY,OAAA;AACZ,uGAAA,aAAa,OAAA;AACb,qGAAA,WAAW,OAAA;AAGf,iEAAiE;AACjE,uCASoB;AAJhB,uGAAA,WAAW,OAAA;AACX,oGAAA,QAAQ,OAAA;AACR,oGAAA,QAAQ,OAAA;AACR,wGAAA,YAAY,OAAA;AAGhB,mBAAmB;AACnB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AACjC,iDAA+D;AAAtD,8GAAA,aAAa,OAAA;AACtB,6CAA6C;AAApC,2GAAA,YAAY,OAAA;AAErB,UAAU;AACV,2CAA0C;AAAjC,wGAAA,UAAU,OAAA","sourcesContent":["/**\n * @webpieces/http-api\n *\n * Core HTTP API definition package.\n * Contains decorators and utilities for defining HTTP APIs.\n *\n * This package is used by:\n * - @webpieces/http-routing (server-side): Routes HTTP requests to controllers\n * - @webpieces/http-client (client-side): Generates HTTP clients from API definitions\n *\n * Architecture:\n * ```\n * http-api (defines the contract)\n * ↑\n * ├── http-routing (server: contract → handlers)\n * └── http-client (client: contract → HTTP requests)\n * ```\n */\n\n// API definition decorators\nexport {\n ApiInterface,\n Get,\n Post,\n Put,\n Delete,\n Patch,\n Path,\n getRoutes,\n isApiInterface,\n RouteMetadata,\n METADATA_KEYS,\n} from './decorators';\n\n// Type validators\nexport { ValidateImplementation } from './validators';\n\n// HTTP errors\nexport {\n ProtocolError,\n HttpError,\n HttpNotFoundError,\n EndpointNotFoundError,\n HttpBadRequestError,\n HttpUnauthorizedError,\n HttpForbiddenError,\n HttpTimeoutError,\n HttpBadGatewayError,\n HttpGatewayTimeoutError,\n HttpInternalServerError,\n HttpVendorError,\n HttpUserError,\n // Error subtype constants\n ENTITY_NOT_FOUND,\n WRONG_LOGIN_TYPE,\n WRONG_LOGIN,\n NOT_APPROVED,\n EMAIL_NOT_CONFIRMED,\n WRONG_DOMAIN,\n WRONG_COMPANY,\n NO_REG_CODE,\n} from './errors';\n\n// Date/Time DTOs and Utilities (inspired by Java Time / JSR-310)\nexport {\n InstantDto,\n DateDto,\n TimeDto,\n DateTimeDto,\n InstantUtil,\n DateUtil,\n TimeUtil,\n DateTimeUtil,\n} from './datetime';\n\n// Platform Headers\nexport { PlatformHeader } from './PlatformHeader';\nexport { PlatformHeadersExtension } from './PlatformHeadersExtension';\nexport { HeaderMethods, ContextReader } from './HeaderMethods';\nexport { HEADER_TYPES } from './HeaderTypes';\n\n// Logging\nexport { LogApiCall } from './LogApiCall';\n"]}