@3sixty/api-processors 0.0.0-stage → 0.20.0-next.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.
Files changed (74) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +24 -2
  3. package/dist/es/data/restRouteProcessor.js +118 -0
  4. package/dist/es/data/restRouteProcessor.js.map +1 -0
  5. package/dist/es/data/socketRouteProcessor.js +131 -0
  6. package/dist/es/data/socketRouteProcessor.js.map +1 -0
  7. package/dist/es/identity/contextIdProcessor.js +69 -0
  8. package/dist/es/identity/contextIdProcessor.js.map +1 -0
  9. package/dist/es/identity/staticContextIdProcessor.js +60 -0
  10. package/dist/es/identity/staticContextIdProcessor.js.map +1 -0
  11. package/dist/es/index.js +19 -0
  12. package/dist/es/index.js.map +1 -0
  13. package/dist/es/logging/loggingProcessor.js +217 -0
  14. package/dist/es/logging/loggingProcessor.js.map +1 -0
  15. package/dist/es/mimeType/jsonLdMimeTypeProcessor.js +38 -0
  16. package/dist/es/mimeType/jsonLdMimeTypeProcessor.js.map +1 -0
  17. package/dist/es/mimeType/jwtMimeTypeProcessor.js +34 -0
  18. package/dist/es/mimeType/jwtMimeTypeProcessor.js.map +1 -0
  19. package/dist/es/models/IContextIdProcessorConfig.js +4 -0
  20. package/dist/es/models/IContextIdProcessorConfig.js.map +1 -0
  21. package/dist/es/models/IContextIdProcessorConstructorOptions.js +2 -0
  22. package/dist/es/models/IContextIdProcessorConstructorOptions.js.map +1 -0
  23. package/dist/es/models/ILoggingProcessorConfig.js +4 -0
  24. package/dist/es/models/ILoggingProcessorConfig.js.map +1 -0
  25. package/dist/es/models/ILoggingProcessorConstructorOptions.js +2 -0
  26. package/dist/es/models/ILoggingProcessorConstructorOptions.js.map +1 -0
  27. package/dist/es/models/IRestRouteProcessorConstructorOptions.js +2 -0
  28. package/dist/es/models/IRestRouteProcessorConstructorOptions.js.map +1 -0
  29. package/dist/es/models/IRouteProcessorConfig.js +4 -0
  30. package/dist/es/models/IRouteProcessorConfig.js.map +1 -0
  31. package/dist/es/models/ISocketRouteProcessorConstructorOptions.js +2 -0
  32. package/dist/es/models/ISocketRouteProcessorConstructorOptions.js.map +1 -0
  33. package/dist/es/models/IStaticContextIdProcessorConfig.js +4 -0
  34. package/dist/es/models/IStaticContextIdProcessorConfig.js.map +1 -0
  35. package/dist/es/models/IStaticContextIdProcessorConstructorOptions.js +2 -0
  36. package/dist/es/models/IStaticContextIdProcessorConstructorOptions.js.map +1 -0
  37. package/dist/types/data/restRouteProcessor.d.ts +36 -0
  38. package/dist/types/data/socketRouteProcessor.d.ts +50 -0
  39. package/dist/types/identity/contextIdProcessor.d.ts +40 -0
  40. package/dist/types/identity/staticContextIdProcessor.d.ts +34 -0
  41. package/dist/types/index.d.ts +16 -0
  42. package/dist/types/logging/loggingProcessor.d.ts +46 -0
  43. package/dist/types/mimeType/jsonLdMimeTypeProcessor.d.ts +26 -0
  44. package/dist/types/mimeType/jwtMimeTypeProcessor.d.ts +26 -0
  45. package/dist/types/models/IContextIdProcessorConfig.d.ts +13 -0
  46. package/dist/types/models/IContextIdProcessorConstructorOptions.d.ts +10 -0
  47. package/dist/types/models/ILoggingProcessorConfig.d.ts +22 -0
  48. package/dist/types/models/ILoggingProcessorConstructorOptions.d.ts +14 -0
  49. package/dist/types/models/IRestRouteProcessorConstructorOptions.d.ts +10 -0
  50. package/dist/types/models/IRouteProcessorConfig.d.ts +9 -0
  51. package/dist/types/models/ISocketRouteProcessorConstructorOptions.d.ts +10 -0
  52. package/dist/types/models/IStaticContextIdProcessorConfig.d.ts +17 -0
  53. package/dist/types/models/IStaticContextIdProcessorConstructorOptions.d.ts +10 -0
  54. package/docs/changelog.md +0 -0
  55. package/docs/examples.md +189 -0
  56. package/docs/reference/classes/ContextIdProcessor.md +127 -0
  57. package/docs/reference/classes/JsonLdMimeTypeProcessor.md +87 -0
  58. package/docs/reference/classes/JwtMimeTypeProcessor.md +87 -0
  59. package/docs/reference/classes/LoggingProcessor.md +149 -0
  60. package/docs/reference/classes/RestRouteProcessor.md +105 -0
  61. package/docs/reference/classes/SocketRouteProcessor.md +183 -0
  62. package/docs/reference/classes/StaticContextIdProcessor.md +101 -0
  63. package/docs/reference/index.md +23 -0
  64. package/docs/reference/interfaces/IContextIdProcessorConfig.md +19 -0
  65. package/docs/reference/interfaces/IContextIdProcessorConstructorOptions.md +11 -0
  66. package/docs/reference/interfaces/ILoggingProcessorConfig.md +36 -0
  67. package/docs/reference/interfaces/ILoggingProcessorConstructorOptions.md +19 -0
  68. package/docs/reference/interfaces/IRestRouteProcessorConstructorOptions.md +11 -0
  69. package/docs/reference/interfaces/IRouteProcessorConfig.md +11 -0
  70. package/docs/reference/interfaces/ISocketRouteProcessorConstructorOptions.md +11 -0
  71. package/docs/reference/interfaces/IStaticContextIdProcessorConfig.md +27 -0
  72. package/docs/reference/interfaces/IStaticContextIdProcessorConstructorOptions.md +11 -0
  73. package/locales/en.json +22 -0
  74. package/package.json +50 -5
@@ -0,0 +1,60 @@
1
+ import { Guards, Is } from "@3sixty/core";
2
+ /**
3
+ * Adds a static context id to the request context.
4
+ */
5
+ export class StaticContextIdProcessor {
6
+ /**
7
+ * Runtime name for the class.
8
+ */
9
+ static CLASS_NAME = "StaticContextIdProcessor";
10
+ /**
11
+ * The fixed identity key for request context.
12
+ * @internal
13
+ */
14
+ _key;
15
+ /**
16
+ * The fixed identity value for request context.
17
+ * @internal
18
+ */
19
+ _value;
20
+ /**
21
+ * Only add the identity if the request is authenticated.
22
+ * @internal
23
+ */
24
+ _authOnly;
25
+ /**
26
+ * Create a new instance of StaticContextIdProcessor.
27
+ * @param options Options for the processor.
28
+ */
29
+ constructor(options) {
30
+ Guards.object(StaticContextIdProcessor.CLASS_NAME, "options", options);
31
+ Guards.object(StaticContextIdProcessor.CLASS_NAME, "options.config", options.config);
32
+ Guards.stringValue(StaticContextIdProcessor.CLASS_NAME, "options.config.key", options.config.key);
33
+ Guards.stringValue(StaticContextIdProcessor.CLASS_NAME, "options.config.value", options.config.value);
34
+ this._key = options.config.key;
35
+ this._value = options.config.value;
36
+ this._authOnly = options.config.authOnly ?? false;
37
+ }
38
+ /**
39
+ * Returns the class name of the component.
40
+ * @returns The class name of the component.
41
+ */
42
+ className() {
43
+ return StaticContextIdProcessor.CLASS_NAME;
44
+ }
45
+ /**
46
+ * Pre process the REST request for the specified route.
47
+ * @param request The incoming request.
48
+ * @param response The outgoing response.
49
+ * @param route The route to process.
50
+ * @param contextIds The context IDs of the request.
51
+ * @param processorState The state handed through the processors.
52
+ * @returns A promise that resolves when the static context ID has been injected into the request.
53
+ */
54
+ async pre(request, response, route, contextIds, processorState) {
55
+ if (!this._authOnly || (!Is.empty(route) && !(route.skipAuth ?? false))) {
56
+ contextIds[this._key] = this._value;
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=staticContextIdProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staticContextIdProcessor.js","sourceRoot":"","sources":["../../../src/identity/staticContextIdProcessor.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAK1C;;GAEG;AACH,MAAM,OAAO,wBAAwB;IACpC;;OAEG;IACI,MAAM,CAAU,UAAU,8BAA8C;IAE/E;;;OAGG;IACc,IAAI,CAAS;IAE9B;;;OAGG;IACc,MAAM,CAAS;IAEhC;;;OAGG;IACc,SAAS,CAAU;IAEpC;;;OAGG;IACH,YAAY,OAAoD;QAC/D,MAAM,CAAC,MAAM,CAAC,wBAAwB,CAAC,UAAU,aAAmB,OAAO,CAAC,CAAC;QAC7E,MAAM,CAAC,MAAM,CACZ,wBAAwB,CAAC,UAAU,oBAEnC,OAAO,CAAC,MAAM,CACd,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,wBAAwB,CAAC,UAAU,wBAEnC,OAAO,CAAC,MAAM,CAAC,GAAG,CAClB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,wBAAwB,CAAC,UAAU,0BAEnC,OAAO,CAAC,MAAM,CAAC,KAAK,CACpB,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;QACnC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC;IACnD,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,wBAAwB,CAAC,UAAU,CAAC;IAC5C,CAAC;IAED;;;;;;;;OAQG;IACI,KAAK,CAAC,GAAG,CACf,OAA2B,EAC3B,QAAuB,EACvB,KAA6B,EAC7B,UAAuB,EACvB,cAAyC;QAEzC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC;YACzE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACrC,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIBaseRoute,\n\tIBaseRouteProcessor,\n\tIHttpResponse,\n\tIHttpServerRequest\n} from \"@3sixty/api-models\";\nimport type { IContextIds } from \"@3sixty/context\";\nimport { Guards, Is } from \"@3sixty/core\";\nimport { nameof } from \"@3sixty/nameof\";\nimport type { IStaticContextIdProcessorConfig } from \"../models/IStaticContextIdProcessorConfig.js\";\nimport type { IStaticContextIdProcessorConstructorOptions } from \"../models/IStaticContextIdProcessorConstructorOptions.js\";\n\n/**\n * Adds a static context id to the request context.\n */\nexport class StaticContextIdProcessor implements IBaseRouteProcessor {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<StaticContextIdProcessor>();\n\n\t/**\n\t * The fixed identity key for request context.\n\t * @internal\n\t */\n\tprivate readonly _key: string;\n\n\t/**\n\t * The fixed identity value for request context.\n\t * @internal\n\t */\n\tprivate readonly _value: string;\n\n\t/**\n\t * Only add the identity if the request is authenticated.\n\t * @internal\n\t */\n\tprivate readonly _authOnly: boolean;\n\n\t/**\n\t * Create a new instance of StaticContextIdProcessor.\n\t * @param options Options for the processor.\n\t */\n\tconstructor(options: IStaticContextIdProcessorConstructorOptions) {\n\t\tGuards.object(StaticContextIdProcessor.CLASS_NAME, nameof(options), options);\n\t\tGuards.object<IStaticContextIdProcessorConfig>(\n\t\t\tStaticContextIdProcessor.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tStaticContextIdProcessor.CLASS_NAME,\n\t\t\tnameof(options.config.key),\n\t\t\toptions.config.key\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tStaticContextIdProcessor.CLASS_NAME,\n\t\t\tnameof(options.config.value),\n\t\t\toptions.config.value\n\t\t);\n\t\tthis._key = options.config.key;\n\t\tthis._value = options.config.value;\n\t\tthis._authOnly = options.config.authOnly ?? false;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn StaticContextIdProcessor.CLASS_NAME;\n\t}\n\n\t/**\n\t * Pre process the REST request for the specified route.\n\t * @param request The incoming request.\n\t * @param response The outgoing response.\n\t * @param route The route to process.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t * @returns A promise that resolves when the static context ID has been injected into the request.\n\t */\n\tpublic async pre(\n\t\trequest: IHttpServerRequest,\n\t\tresponse: IHttpResponse,\n\t\troute: IBaseRoute | undefined,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: { [id: string]: unknown }\n\t): Promise<void> {\n\t\tif (!this._authOnly || (!Is.empty(route) && !(route.skipAuth ?? false))) {\n\t\t\tcontextIds[this._key] = this._value;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,19 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export * from "./data/restRouteProcessor.js";
4
+ export * from "./data/socketRouteProcessor.js";
5
+ export * from "./identity/contextIdProcessor.js";
6
+ export * from "./identity/staticContextIdProcessor.js";
7
+ export * from "./logging/loggingProcessor.js";
8
+ export * from "./mimeType/jsonLdMimeTypeProcessor.js";
9
+ export * from "./mimeType/jwtMimeTypeProcessor.js";
10
+ export * from "./models/IContextIdProcessorConfig.js";
11
+ export * from "./models/IContextIdProcessorConstructorOptions.js";
12
+ export * from "./models/ILoggingProcessorConfig.js";
13
+ export * from "./models/ILoggingProcessorConstructorOptions.js";
14
+ export * from "./models/IRestRouteProcessorConstructorOptions.js";
15
+ export * from "./models/IRouteProcessorConfig.js";
16
+ export * from "./models/ISocketRouteProcessorConstructorOptions.js";
17
+ export * from "./models/IStaticContextIdProcessorConfig.js";
18
+ export * from "./models/IStaticContextIdProcessorConstructorOptions.js";
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,mDAAmD,CAAC;AAClE,cAAc,qCAAqC,CAAC;AACpD,cAAc,iDAAiD,CAAC;AAChE,cAAc,mDAAmD,CAAC;AAClE,cAAc,mCAAmC,CAAC;AAClD,cAAc,qDAAqD,CAAC;AACpE,cAAc,6CAA6C,CAAC;AAC5D,cAAc,yDAAyD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./data/restRouteProcessor.js\";\nexport * from \"./data/socketRouteProcessor.js\";\nexport * from \"./identity/contextIdProcessor.js\";\nexport * from \"./identity/staticContextIdProcessor.js\";\nexport * from \"./logging/loggingProcessor.js\";\nexport * from \"./mimeType/jsonLdMimeTypeProcessor.js\";\nexport * from \"./mimeType/jwtMimeTypeProcessor.js\";\nexport * from \"./models/IContextIdProcessorConfig.js\";\nexport * from \"./models/IContextIdProcessorConstructorOptions.js\";\nexport * from \"./models/ILoggingProcessorConfig.js\";\nexport * from \"./models/ILoggingProcessorConstructorOptions.js\";\nexport * from \"./models/IRestRouteProcessorConstructorOptions.js\";\nexport * from \"./models/IRouteProcessorConfig.js\";\nexport * from \"./models/ISocketRouteProcessorConstructorOptions.js\";\nexport * from \"./models/IStaticContextIdProcessorConfig.js\";\nexport * from \"./models/IStaticContextIdProcessorConstructorOptions.js\";\n"]}
@@ -0,0 +1,217 @@
1
+ import { Coerce, ComponentFactory, Is, ObjectHelper } from "@3sixty/core";
2
+ import { HeaderTypes, HttpStatusCode, MimeTypes } from "@3sixty/web";
3
+ /**
4
+ * Process the REST request and log its information.
5
+ */
6
+ export class LoggingProcessor {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static CLASS_NAME = "LoggingProcessor";
11
+ /**
12
+ * The component for logging the information.
13
+ * @internal
14
+ */
15
+ _logging;
16
+ /**
17
+ * Include the body objects when logging the information.
18
+ * @internal
19
+ */
20
+ _includeBody;
21
+ /**
22
+ * Show the full base64 content for data, default to abbreviate.
23
+ * @internal
24
+ */
25
+ _fullBase64;
26
+ /**
27
+ * List of property names to obfuscate, defaults to "password".
28
+ * @internal
29
+ */
30
+ _obfuscateProperties;
31
+ /**
32
+ * Request URL path prefixes to skip logging, defaults to ["/logging"].
33
+ * @internal
34
+ */
35
+ _excludePaths;
36
+ /**
37
+ * Create a new instance of LoggingProcessor.
38
+ * @param options Options for the processor.
39
+ */
40
+ constructor(options) {
41
+ this._logging = ComponentFactory.getIfExists(options?.loggingComponentType);
42
+ this._includeBody = options?.config?.includeBody ?? false;
43
+ this._fullBase64 = options?.config?.fullBase64 ?? false;
44
+ this._obfuscateProperties = options?.config?.obfuscateProperties ?? ["password"];
45
+ this._excludePaths = options?.config?.excludePaths ?? ["/logging"];
46
+ }
47
+ /**
48
+ * Returns the class name of the component.
49
+ * @returns The class name of the component.
50
+ */
51
+ className() {
52
+ return LoggingProcessor.CLASS_NAME;
53
+ }
54
+ /**
55
+ * Pre process the REST request for the specified route.
56
+ * @param request The incoming request.
57
+ * @param response The outgoing response.
58
+ * @param route The route to process.
59
+ * @param contextIds The context IDs of the request.
60
+ * @param processorState The state handed through the processors.
61
+ * @returns A promise that resolves when the pre-processing log entry has been written.
62
+ */
63
+ async pre(request, response, route, contextIds, processorState) {
64
+ let requestUrl = "";
65
+ if (Is.stringValue(request.url)) {
66
+ // Socket paths do not have a prefix so just use the whole url.
67
+ if (request.url.startsWith("http")) {
68
+ requestUrl = new URL(request.url).pathname;
69
+ }
70
+ else {
71
+ requestUrl = request.url;
72
+ }
73
+ }
74
+ if (this._excludePaths.some(p => requestUrl.startsWith(p))) {
75
+ return;
76
+ }
77
+ const now = process.hrtime.bigint();
78
+ processorState.requestStart = now;
79
+ const contentType = request.headers?.[HeaderTypes.ContentType];
80
+ const isJson = this.isMimeJson(contentType);
81
+ await this._logging?.log({
82
+ level: "info",
83
+ source: LoggingProcessor.CLASS_NAME,
84
+ ts: Date.now(),
85
+ message: "requestMessage",
86
+ data: {
87
+ method: request.method,
88
+ requestUrl,
89
+ body: this._includeBody && isJson
90
+ ? this.processJson("body", ObjectHelper.clone(request?.body))
91
+ : undefined
92
+ }
93
+ });
94
+ }
95
+ /**
96
+ * Post process the REST request for the specified route.
97
+ * @param request The incoming request.
98
+ * @param response The outgoing response.
99
+ * @param route The route to process.
100
+ * @param contextIds The context IDs of the request.
101
+ * @param processorState The state handed through the processors.
102
+ * @returns A promise that resolves when the post-processing log entry has been written.
103
+ */
104
+ async post(request, response, route, contextIds, processorState) {
105
+ let requestUrl = "";
106
+ if (Is.stringValue(request.url)) {
107
+ // Socket paths do not have a prefix so just use the whole url.
108
+ if (request.url.startsWith("http")) {
109
+ requestUrl = new URL(request.url).pathname;
110
+ }
111
+ else {
112
+ requestUrl = request.url;
113
+ }
114
+ }
115
+ if (this._excludePaths.some(p => requestUrl.startsWith(p))) {
116
+ return;
117
+ }
118
+ let data;
119
+ if (this._includeBody) {
120
+ const contentType = response.headers?.[HeaderTypes.ContentType];
121
+ const isJson = this.isMimeJson(contentType);
122
+ const contentLength = response.headers?.[HeaderTypes.ContentLength];
123
+ if (isJson) {
124
+ data = {
125
+ body: this.processJson("body", ObjectHelper.clone(response.body))
126
+ };
127
+ }
128
+ else {
129
+ const dataParts = {};
130
+ if (Is.stringValue(contentType)) {
131
+ dataParts["Content Type"] = contentType;
132
+ }
133
+ if (Is.stringValue(contentLength)) {
134
+ dataParts["Content Length"] = contentLength;
135
+ }
136
+ if (Object.keys(dataParts).length > 0) {
137
+ data = {
138
+ headers: dataParts
139
+ };
140
+ }
141
+ }
142
+ }
143
+ const now = process.hrtime.bigint();
144
+ const start = Coerce.bigint(processorState.requestStart) ?? now;
145
+ const elapsed = now - start;
146
+ const elapsedMicroSeconds = Math.floor(Number(elapsed) / 1000);
147
+ if (Is.number(response.statusCode) && response.statusCode >= HttpStatusCode.badRequest) {
148
+ await this._logging?.log({
149
+ level: "error",
150
+ source: LoggingProcessor.CLASS_NAME,
151
+ ts: Date.now(),
152
+ message: "responseMessage",
153
+ data: {
154
+ statusCode: response.statusCode,
155
+ method: request.method,
156
+ requestUrl: requestUrl ?? "",
157
+ elapsedMicroSeconds,
158
+ ...data
159
+ }
160
+ });
161
+ }
162
+ else {
163
+ await this._logging?.log({
164
+ level: "info",
165
+ source: LoggingProcessor.CLASS_NAME,
166
+ ts: Date.now(),
167
+ message: "responseMessage",
168
+ data: {
169
+ statusCode: response.statusCode,
170
+ method: request.method,
171
+ requestUrl: requestUrl ?? "",
172
+ elapsedMicroSeconds,
173
+ ...data
174
+ }
175
+ });
176
+ }
177
+ }
178
+ /**
179
+ * Process the JSON.
180
+ * @param propName The property name to process.
181
+ * @param propValue The property to process.
182
+ * @returns The processed property.
183
+ * @internal
184
+ */
185
+ processJson(propName, propValue) {
186
+ if (Is.array(propValue)) {
187
+ for (let i = 0; i < propValue.length; i++) {
188
+ propValue[i] = this.processJson(`${i}`, propValue[i]);
189
+ }
190
+ }
191
+ else if (Is.object(propValue)) {
192
+ for (const key of Object.keys(propValue)) {
193
+ propValue[key] = this.processJson(key, propValue[key]);
194
+ }
195
+ }
196
+ else if (!this._fullBase64 && Is.stringBase64(propValue) && propValue.length > 256) {
197
+ propValue = "<base64>";
198
+ }
199
+ else if (Is.string(propValue) &&
200
+ this._obfuscateProperties.some(op => new RegExp(op).test(propName))) {
201
+ propValue = "**************";
202
+ }
203
+ return propValue;
204
+ }
205
+ /**
206
+ * Check if the content type is JSON.
207
+ * @param contentType The content type to check.
208
+ * @returns True if the content type is JSON, false otherwise.
209
+ * @internal
210
+ */
211
+ isMimeJson(contentType) {
212
+ return Is.stringValue(contentType)
213
+ ? contentType.includes(MimeTypes.Json) || contentType.includes(MimeTypes.JsonLd)
214
+ : false;
215
+ }
216
+ }
217
+ //# sourceMappingURL=loggingProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loggingProcessor.js","sourceRoot":"","sources":["../../../src/logging/loggingProcessor.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type {\n\tIBaseRoute,\n\tIBaseRouteProcessor,\n\tIHttpResponse,\n\tIHttpServerRequest\n} from \"@3sixty/api-models\";\nimport type { IContextIds } from \"@3sixty/context\";\nimport { Coerce, ComponentFactory, Is, ObjectHelper } from \"@3sixty/core\";\nimport type { ILoggingComponent } from \"@3sixty/logging-models\";\nimport { nameof } from \"@3sixty/nameof\";\nimport { HeaderTypes, HttpStatusCode, MimeTypes } from \"@3sixty/web\";\nimport type { ILoggingProcessorConstructorOptions } from \"../models/ILoggingProcessorConstructorOptions.js\";\n\n/**\n * Process the REST request and log its information.\n */\nexport class LoggingProcessor implements IBaseRouteProcessor {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<LoggingProcessor>();\n\n\t/**\n\t * The component for logging the information.\n\t * @internal\n\t */\n\tprivate readonly _logging?: ILoggingComponent;\n\n\t/**\n\t * Include the body objects when logging the information.\n\t * @internal\n\t */\n\tprivate readonly _includeBody: boolean;\n\n\t/**\n\t * Show the full base64 content for data, default to abbreviate.\n\t * @internal\n\t */\n\tprivate readonly _fullBase64: boolean;\n\n\t/**\n\t * List of property names to obfuscate, defaults to \"password\".\n\t * @internal\n\t */\n\tprivate readonly _obfuscateProperties: string[];\n\n\t/**\n\t * Request URL path prefixes to skip logging, defaults to [\"/logging\"].\n\t * @internal\n\t */\n\tprivate readonly _excludePaths: string[];\n\n\t/**\n\t * Create a new instance of LoggingProcessor.\n\t * @param options Options for the processor.\n\t */\n\tconstructor(options?: ILoggingProcessorConstructorOptions) {\n\t\tthis._logging = ComponentFactory.getIfExists(options?.loggingComponentType);\n\t\tthis._includeBody = options?.config?.includeBody ?? false;\n\t\tthis._fullBase64 = options?.config?.fullBase64 ?? false;\n\t\tthis._obfuscateProperties = options?.config?.obfuscateProperties ?? [\"password\"];\n\t\tthis._excludePaths = options?.config?.excludePaths ?? [\"/logging\"];\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn LoggingProcessor.CLASS_NAME;\n\t}\n\n\t/**\n\t * Pre process the REST request for the specified route.\n\t * @param request The incoming request.\n\t * @param response The outgoing response.\n\t * @param route The route to process.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t * @returns A promise that resolves when the pre-processing log entry has been written.\n\t */\n\tpublic async pre(\n\t\trequest: IHttpServerRequest,\n\t\tresponse: IHttpResponse,\n\t\troute: IBaseRoute | undefined,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: { [id: string]: unknown }\n\t): Promise<void> {\n\t\tlet requestUrl = \"\";\n\t\tif (Is.stringValue(request.url)) {\n\t\t\t// Socket paths do not have a prefix so just use the whole url.\n\t\t\tif (request.url.startsWith(\"http\")) {\n\t\t\t\trequestUrl = new URL(request.url).pathname;\n\t\t\t} else {\n\t\t\t\trequestUrl = request.url;\n\t\t\t}\n\t\t}\n\n\t\tif (this._excludePaths.some(p => requestUrl.startsWith(p))) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst now = process.hrtime.bigint();\n\t\tprocessorState.requestStart = now;\n\n\t\tconst contentType = request.headers?.[HeaderTypes.ContentType];\n\t\tconst isJson = this.isMimeJson(contentType);\n\n\t\tawait this._logging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: LoggingProcessor.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"requestMessage\",\n\t\t\tdata: {\n\t\t\t\tmethod: request.method,\n\t\t\t\trequestUrl,\n\t\t\t\tbody:\n\t\t\t\t\tthis._includeBody && isJson\n\t\t\t\t\t\t? this.processJson(\"body\", ObjectHelper.clone(request?.body))\n\t\t\t\t\t\t: undefined\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Post process the REST request for the specified route.\n\t * @param request The incoming request.\n\t * @param response The outgoing response.\n\t * @param route The route to process.\n\t * @param contextIds The context IDs of the request.\n\t * @param processorState The state handed through the processors.\n\t * @returns A promise that resolves when the post-processing log entry has been written.\n\t */\n\tpublic async post(\n\t\trequest: IHttpServerRequest,\n\t\tresponse: IHttpResponse,\n\t\troute: IBaseRoute | undefined,\n\t\tcontextIds: IContextIds,\n\t\tprocessorState: { [id: string]: unknown }\n\t): Promise<void> {\n\t\tlet requestUrl = \"\";\n\t\tif (Is.stringValue(request.url)) {\n\t\t\t// Socket paths do not have a prefix so just use the whole url.\n\t\t\tif (request.url.startsWith(\"http\")) {\n\t\t\t\trequestUrl = new URL(request.url).pathname;\n\t\t\t} else {\n\t\t\t\trequestUrl = request.url;\n\t\t\t}\n\t\t}\n\n\t\tif (this._excludePaths.some(p => requestUrl.startsWith(p))) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet data: { [id: string]: unknown } | undefined;\n\t\tif (this._includeBody) {\n\t\t\tconst contentType = response.headers?.[HeaderTypes.ContentType];\n\t\t\tconst isJson = this.isMimeJson(contentType);\n\t\t\tconst contentLength = response.headers?.[HeaderTypes.ContentLength];\n\t\t\tif (isJson) {\n\t\t\t\tdata = {\n\t\t\t\t\tbody: this.processJson(\"body\", ObjectHelper.clone(response.body))\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tconst dataParts: { [id: string]: string } = {};\n\t\t\t\tif (Is.stringValue(contentType)) {\n\t\t\t\t\tdataParts[\"Content Type\"] = contentType;\n\t\t\t\t}\n\t\t\t\tif (Is.stringValue(contentLength)) {\n\t\t\t\t\tdataParts[\"Content Length\"] = contentLength;\n\t\t\t\t}\n\t\t\t\tif (Object.keys(dataParts).length > 0) {\n\t\t\t\t\tdata = {\n\t\t\t\t\t\theaders: dataParts\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst now = process.hrtime.bigint();\n\t\tconst start = Coerce.bigint(processorState.requestStart) ?? now;\n\t\tconst elapsed = now - start;\n\t\tconst elapsedMicroSeconds = Math.floor(Number(elapsed) / 1000);\n\n\t\tif (Is.number(response.statusCode) && response.statusCode >= HttpStatusCode.badRequest) {\n\t\t\tawait this._logging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: LoggingProcessor.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"responseMessage\",\n\t\t\t\tdata: {\n\t\t\t\t\tstatusCode: response.statusCode,\n\t\t\t\t\tmethod: request.method,\n\t\t\t\t\trequestUrl: requestUrl ?? \"\",\n\t\t\t\t\telapsedMicroSeconds,\n\t\t\t\t\t...data\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tawait this._logging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: LoggingProcessor.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"responseMessage\",\n\t\t\t\tdata: {\n\t\t\t\t\tstatusCode: response.statusCode,\n\t\t\t\t\tmethod: request.method,\n\t\t\t\t\trequestUrl: requestUrl ?? \"\",\n\t\t\t\t\telapsedMicroSeconds,\n\t\t\t\t\t...data\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Process the JSON.\n\t * @param propName The property name to process.\n\t * @param propValue The property to process.\n\t * @returns The processed property.\n\t * @internal\n\t */\n\tprivate processJson(propName: string, propValue: unknown): unknown {\n\t\tif (Is.array(propValue)) {\n\t\t\tfor (let i = 0; i < propValue.length; i++) {\n\t\t\t\tpropValue[i] = this.processJson(`${i}`, propValue[i]);\n\t\t\t}\n\t\t} else if (Is.object(propValue)) {\n\t\t\tfor (const key of Object.keys(propValue)) {\n\t\t\t\tpropValue[key] = this.processJson(key, propValue[key]);\n\t\t\t}\n\t\t} else if (!this._fullBase64 && Is.stringBase64(propValue) && propValue.length > 256) {\n\t\t\tpropValue = \"<base64>\";\n\t\t} else if (\n\t\t\tIs.string(propValue) &&\n\t\t\tthis._obfuscateProperties.some(op => new RegExp(op).test(propName))\n\t\t) {\n\t\t\tpropValue = \"**************\";\n\t\t}\n\n\t\treturn propValue;\n\t}\n\n\t/**\n\t * Check if the content type is JSON.\n\t * @param contentType The content type to check.\n\t * @returns True if the content type is JSON, false otherwise.\n\t * @internal\n\t */\n\tprivate isMimeJson(contentType: string | string[] | undefined): boolean {\n\t\treturn Is.stringValue(contentType)\n\t\t\t? contentType.includes(MimeTypes.Json) || contentType.includes(MimeTypes.JsonLd)\n\t\t\t: false;\n\t}\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import { GeneralError, Is, ObjectHelper } from "@3sixty/core";
2
+ import { MimeTypes } from "@3sixty/web";
3
+ /**
4
+ * Process the JSON-LD mime type.
5
+ */
6
+ export class JsonLdMimeTypeProcessor {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static CLASS_NAME = "JsonLdMimeTypeProcessor";
11
+ /**
12
+ * Returns the class name of the component.
13
+ * @returns The class name of the component.
14
+ */
15
+ className() {
16
+ return JsonLdMimeTypeProcessor.CLASS_NAME;
17
+ }
18
+ /**
19
+ * Get the MIME types that this handler can handle.
20
+ * @returns The MIME types that this handler can handle.
21
+ */
22
+ getTypes() {
23
+ return [MimeTypes.JsonLd];
24
+ }
25
+ /**
26
+ * Handle content.
27
+ * @param body The body to process.
28
+ * @returns The processed body.
29
+ */
30
+ async handle(body) {
31
+ const json = ObjectHelper.fromBytes(body);
32
+ if (Is.empty(json) || Is.empty(json["@context"])) {
33
+ throw new GeneralError(JsonLdMimeTypeProcessor.CLASS_NAME, "invalidJsonLd");
34
+ }
35
+ return json;
36
+ }
37
+ }
38
+ //# sourceMappingURL=jsonLdMimeTypeProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonLdMimeTypeProcessor.js","sourceRoot":"","sources":["../../../src/mimeType/jsonLdMimeTypeProcessor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,MAAM,OAAO,uBAAuB;IACnC;;OAEG;IACI,MAAM,CAAU,UAAU,6BAA6C;IAE9E;;;OAGG;IACI,SAAS;QACf,OAAO,uBAAuB,CAAC,UAAU,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACI,QAAQ;QACd,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,IAAgB;QACnC,MAAM,IAAI,GAAG,YAAY,CAAC,SAAS,CAA0B,IAAI,CAAC,CAAC;QAEnE,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,YAAY,CAAC,uBAAuB,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAC7E,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IMimeTypeProcessor } from \"@3sixty/api-models\";\nimport { GeneralError, Is, ObjectHelper } from \"@3sixty/core\";\nimport { nameof } from \"@3sixty/nameof\";\nimport { MimeTypes } from \"@3sixty/web\";\n\n/**\n * Process the JSON-LD mime type.\n */\nexport class JsonLdMimeTypeProcessor implements IMimeTypeProcessor {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<JsonLdMimeTypeProcessor>();\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn JsonLdMimeTypeProcessor.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the MIME types that this handler can handle.\n\t * @returns The MIME types that this handler can handle.\n\t */\n\tpublic getTypes(): string[] {\n\t\treturn [MimeTypes.JsonLd];\n\t}\n\n\t/**\n\t * Handle content.\n\t * @param body The body to process.\n\t * @returns The processed body.\n\t */\n\tpublic async handle(body: Uint8Array): Promise<unknown> {\n\t\tconst json = ObjectHelper.fromBytes<{ \"@context\"?: string }>(body);\n\n\t\tif (Is.empty(json) || Is.empty(json[\"@context\"])) {\n\t\t\tthrow new GeneralError(JsonLdMimeTypeProcessor.CLASS_NAME, \"invalidJsonLd\");\n\t\t}\n\n\t\treturn json;\n\t}\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import { Converter } from "@3sixty/core";
2
+ import { MimeTypes } from "@3sixty/web";
3
+ /**
4
+ * Process the JWT mime type.
5
+ */
6
+ export class JwtMimeTypeProcessor {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static CLASS_NAME = "JwtMimeTypeProcessor";
11
+ /**
12
+ * Returns the class name of the component.
13
+ * @returns The class name of the component.
14
+ */
15
+ className() {
16
+ return JwtMimeTypeProcessor.CLASS_NAME;
17
+ }
18
+ /**
19
+ * Get the MIME types that this handler can handle.
20
+ * @returns The MIME types that this handler can handle.
21
+ */
22
+ getTypes() {
23
+ return [MimeTypes.Jwt];
24
+ }
25
+ /**
26
+ * Handle content.
27
+ * @param body The body to process.
28
+ * @returns The processed body.
29
+ */
30
+ async handle(body) {
31
+ return Converter.bytesToUtf8(body);
32
+ }
33
+ }
34
+ //# sourceMappingURL=jwtMimeTypeProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwtMimeTypeProcessor.js","sourceRoot":"","sources":["../../../src/mimeType/jwtMimeTypeProcessor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;GAEG;AACH,MAAM,OAAO,oBAAoB;IAChC;;OAEG;IACI,MAAM,CAAU,UAAU,0BAA0C;IAE3E;;;OAGG;IACI,SAAS;QACf,OAAO,oBAAoB,CAAC,UAAU,CAAC;IACxC,CAAC;IAED;;;OAGG;IACI,QAAQ;QACd,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,IAAgB;QACnC,OAAO,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IMimeTypeProcessor } from \"@3sixty/api-models\";\nimport { Converter } from \"@3sixty/core\";\nimport { nameof } from \"@3sixty/nameof\";\nimport { MimeTypes } from \"@3sixty/web\";\n\n/**\n * Process the JWT mime type.\n */\nexport class JwtMimeTypeProcessor implements IMimeTypeProcessor {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<JwtMimeTypeProcessor>();\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn JwtMimeTypeProcessor.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get the MIME types that this handler can handle.\n\t * @returns The MIME types that this handler can handle.\n\t */\n\tpublic getTypes(): string[] {\n\t\treturn [MimeTypes.Jwt];\n\t}\n\n\t/**\n\t * Handle content.\n\t * @param body The body to process.\n\t * @returns The processed body.\n\t */\n\tpublic async handle(body: Uint8Array): Promise<unknown> {\n\t\treturn Converter.bytesToUtf8(body);\n\t}\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=IContextIdProcessorConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IContextIdProcessorConfig.js","sourceRoot":"","sources":["../../../src/models/IContextIdProcessorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the context id processor.\n */\nexport interface IContextIdProcessorConfig {\n\t/**\n\t * The fixed identity key for request context.\n\t */\n\tkey: string;\n\n\t/**\n\t * Only add the identity if the request is authenticated.\n\t */\n\tauthOnly?: boolean;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IContextIdProcessorConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IContextIdProcessorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IContextIdProcessorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IContextIdProcessorConfig } from \"./IContextIdProcessorConfig.js\";\n\n/**\n * Options for the ContextIdProcessor constructor.\n */\nexport interface IContextIdProcessorConstructorOptions {\n\t/**\n\t * The configuration for the processor.\n\t */\n\tconfig: IContextIdProcessorConfig;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ILoggingProcessorConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ILoggingProcessorConfig.js","sourceRoot":"","sources":["../../../src/models/ILoggingProcessorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the request logging processor.\n */\nexport interface ILoggingProcessorConfig {\n\t/**\n\t * Include the body objects when logging the information.\n\t */\n\tincludeBody?: boolean;\n\n\t/**\n\t * Show the full base64 content for data, default to abbreviate.\n\t */\n\tfullBase64?: boolean;\n\n\t/**\n\t * List of property names to obfuscate, can be regex, defaults to \"password\".\n\t */\n\tobfuscateProperties?: string[];\n\n\t/**\n\t * Request URL path prefixes to exclude from logging, defaults to [\"/logging\"].\n\t * Use this to prevent the logging endpoint itself from appearing in its own output.\n\t */\n\texcludePaths?: string[];\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ILoggingProcessorConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ILoggingProcessorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ILoggingProcessorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ILoggingProcessorConfig } from \"./ILoggingProcessorConfig.js\";\n\n/**\n * Options for the LoggingProcessor constructor.\n */\nexport interface ILoggingProcessorConstructorOptions {\n\t/**\n\t * The type for the logging component.\n\t */\n\tloggingComponentType?: string;\n\n\t/**\n\t * The configuration for the logging processor.\n\t */\n\tconfig?: ILoggingProcessorConfig;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IRestRouteProcessorConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IRestRouteProcessorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IRestRouteProcessorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRouteProcessorConfig } from \"../models/IRouteProcessorConfig.js\";\n\n/**\n * Options for the RestRouteProcessor constructor.\n */\nexport interface IRestRouteProcessorConstructorOptions {\n\t/**\n\t * The configuration for the processor.\n\t */\n\tconfig?: IRouteProcessorConfig;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=IRouteProcessorConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IRouteProcessorConfig.js","sourceRoot":"","sources":["../../../src/models/IRouteProcessorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the route processor.\n */\nexport interface IRouteProcessorConfig {\n\t/**\n\t * Include the stack with errors.\n\t */\n\tincludeErrorStack?: boolean;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ISocketRouteProcessorConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ISocketRouteProcessorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ISocketRouteProcessorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRouteProcessorConfig } from \"./IRouteProcessorConfig.js\";\n\n/**\n * Options for the SocketRouteProcessor constructor.\n */\nexport interface ISocketRouteProcessorConstructorOptions {\n\t/**\n\t * The configuration for the processor.\n\t */\n\tconfig?: IRouteProcessorConfig;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=IStaticContextIdProcessorConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IStaticContextIdProcessorConfig.js","sourceRoot":"","sources":["../../../src/models/IStaticContextIdProcessorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the static id processor.\n */\nexport interface IStaticContextIdProcessorConfig {\n\t/**\n\t * The fixed identity key for request context.\n\t */\n\tkey: string;\n\n\t/**\n\t * The fixed identity value for request context.\n\t */\n\tvalue: string;\n\n\t/**\n\t * Only add the identity if the request is authenticated.\n\t */\n\tauthOnly?: boolean;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=IStaticContextIdProcessorConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IStaticContextIdProcessorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/IStaticContextIdProcessorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IStaticContextIdProcessorConfig } from \"./IStaticContextIdProcessorConfig.js\";\n\n/**\n * Options for the StaticContextIdProcessor constructor.\n */\nexport interface IStaticContextIdProcessorConstructorOptions {\n\t/**\n\t * The configuration for the processor.\n\t */\n\tconfig: IStaticContextIdProcessorConfig;\n}\n"]}
@@ -0,0 +1,36 @@
1
+ import { type IHttpResponse, type IHttpServerRequest, type IRestRoute, type IRestRouteProcessor } from "@3sixty/api-models";
2
+ import type { IRestRouteProcessorConstructorOptions } from "../models/IRestRouteProcessorConstructorOptions.js";
3
+ /**
4
+ * Process the REST request and hands it on to the route handler.
5
+ */
6
+ export declare class RestRouteProcessor implements IRestRouteProcessor {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static readonly CLASS_NAME: string;
11
+ /**
12
+ * Create a new instance of RouteProcessor.
13
+ * @param options Options for the processor.
14
+ */
15
+ constructor(options?: IRestRouteProcessorConstructorOptions);
16
+ /**
17
+ * Returns the class name of the component.
18
+ * @returns The class name of the component.
19
+ */
20
+ className(): string;
21
+ /**
22
+ * Process the REST request for the specified route.
23
+ * @param request The incoming request.
24
+ * @param response The outgoing response.
25
+ * @param route The route to process.
26
+ * @param processorState The state handed through the processors.
27
+ * @param componentTypes The component types for the request.
28
+ * @param componentTypes.loggingComponentType The logging component type.
29
+ * @returns A promise that resolves when the request has been processed and the response populated.
30
+ */
31
+ process(request: IHttpServerRequest, response: IHttpResponse, route: IRestRoute | undefined, processorState: {
32
+ [id: string]: unknown;
33
+ }, componentTypes?: {
34
+ loggingComponentType?: string;
35
+ }): Promise<void>;
36
+ }
@@ -0,0 +1,50 @@
1
+ import { type IHttpResponse, type ISocketRoute, type ISocketRouteProcessor, type ISocketServerRequest } from "@3sixty/api-models";
2
+ import type { ISocketRouteProcessorConstructorOptions } from "../models/ISocketRouteProcessorConstructorOptions.js";
3
+ /**
4
+ * Process the socket request and hands it on to the route handler.
5
+ */
6
+ export declare class SocketRouteProcessor implements ISocketRouteProcessor {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static readonly CLASS_NAME: string;
11
+ /**
12
+ * Create a new instance of SocketRouteProcessor.
13
+ * @param options Options for the processor.
14
+ */
15
+ constructor(options?: ISocketRouteProcessorConstructorOptions);
16
+ /**
17
+ * Returns the class name of the component.
18
+ * @returns The class name of the component.
19
+ */
20
+ className(): string;
21
+ /**
22
+ * Process the connected event.
23
+ * @param request The server request object containing the socket id and other parameters.
24
+ * @param route The route being requested, if a matching one was found.
25
+ * @param loggingComponentType The logging component type for the request.
26
+ * @returns Promise that resolves when the request is processed.
27
+ */
28
+ connected(request: ISocketServerRequest, route: ISocketRoute | undefined, loggingComponentType?: string): Promise<void>;
29
+ /**
30
+ * Process the disconnected event.
31
+ * @param request The server request object containing the socket id and other parameters.
32
+ * @param route The route being requested, if a matching one was found.
33
+ * @param loggingComponentType The logging component type for the request.
34
+ * @returns Promise that resolves when the request is processed.
35
+ */
36
+ disconnected(request: ISocketServerRequest, route: ISocketRoute | undefined, loggingComponentType?: string): Promise<void>;
37
+ /**
38
+ * Process the socket request for the specified route.
39
+ * @param request The incoming request.
40
+ * @param response The outgoing response.
41
+ * @param route The route to process.
42
+ * @param processorState The state handed through the processors.
43
+ * @param responseEmitter The function to emit a response.
44
+ * @param loggingComponentType The logging component type for the request.
45
+ * @returns A promise that resolves when the request has been processed and the response emitted.
46
+ */
47
+ process(request: ISocketServerRequest, response: IHttpResponse, route: ISocketRoute | undefined, processorState: {
48
+ [id: string]: unknown;
49
+ }, responseEmitter: (topic: string, response: IHttpResponse) => Promise<void>, loggingComponentType?: string): Promise<void>;
50
+ }