@villedemontreal/correlation-id 5.3.2

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/src/config/configs.d.ts +16 -0
  4. package/dist/src/config/configs.js +26 -0
  5. package/dist/src/config/configs.js.map +1 -0
  6. package/dist/src/config/constants.d.ts +27 -0
  7. package/dist/src/config/constants.js +27 -0
  8. package/dist/src/config/constants.js.map +1 -0
  9. package/dist/src/config/init.d.ts +15 -0
  10. package/dist/src/config/init.js +34 -0
  11. package/dist/src/config/init.js.map +1 -0
  12. package/dist/src/index.d.ts +3 -0
  13. package/dist/src/index.js +25 -0
  14. package/dist/src/index.js.map +1 -0
  15. package/dist/src/middleware/correlationIdMiddleware.d.ts +8 -0
  16. package/dist/src/middleware/correlationIdMiddleware.js +43 -0
  17. package/dist/src/middleware/correlationIdMiddleware.js.map +1 -0
  18. package/dist/src/middleware/correlationIdMiddleware.test.d.ts +1 -0
  19. package/dist/src/middleware/correlationIdMiddleware.test.js +306 -0
  20. package/dist/src/middleware/correlationIdMiddleware.test.js.map +1 -0
  21. package/dist/src/services/correlationIdService.d.ts +68 -0
  22. package/dist/src/services/correlationIdService.js +166 -0
  23. package/dist/src/services/correlationIdService.js.map +1 -0
  24. package/dist/src/services/correlationIdService.test.d.ts +1 -0
  25. package/dist/src/services/correlationIdService.test.js +215 -0
  26. package/dist/src/services/correlationIdService.test.js.map +1 -0
  27. package/dist/src/utils/logger.d.ts +11 -0
  28. package/dist/src/utils/logger.js +54 -0
  29. package/dist/src/utils/logger.js.map +1 -0
  30. package/dist/src/utils/testingConfigurations.d.ts +9 -0
  31. package/dist/src/utils/testingConfigurations.js +18 -0
  32. package/dist/src/utils/testingConfigurations.js.map +1 -0
  33. package/package.json +62 -0
  34. package/src/config/configs.ts +26 -0
  35. package/src/config/constants.ts +40 -0
  36. package/src/config/init.ts +33 -0
  37. package/src/index.ts +9 -0
  38. package/src/middleware/correlationIdMiddleware.test.ts +335 -0
  39. package/src/middleware/correlationIdMiddleware.ts +45 -0
  40. package/src/services/correlationIdService.test.ts +255 -0
  41. package/src/services/correlationIdService.ts +255 -0
  42. package/src/utils/logger.ts +53 -0
  43. package/src/utils/testingConfigurations.ts +14 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Ville de Montréal and other contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # @villedemontreal/correlation-id
2
+ Module fournissant un middleware Express pour propager ou/et générer le correlation id et un service permettant de le récupérer à n'importe quel moment de la requête sans devoir le propager à la main.
3
+
4
+
5
+ ## Installation
6
+ Installer la bibliothèque:
7
+ ```shell
8
+ npm install --save @villedemontreal/correlation-id
9
+ ```
10
+
11
+ Avec yarn:
12
+ ```shell
13
+ yarn add @villedemontreal/correlation-id
14
+ ```
15
+
16
+ ## Mise en garde!
17
+
18
+ **Attention!** Pour que les Correlation Ids soient les bons partout dans une application, il faut que ces cid aient été
19
+ retournées *par le même `correlationIdService`*! Vous ne devez pas importer un `correlationIdService` dans une librairie dans le
20
+ but d'utiliser `correlationIdService.getId()` : cela ne retournera pas le bon cid!
21
+
22
+ Cette librarie ne devrait donc qu'être utilisée que par un projet API racine, et non dans une librairie. C'est à
23
+ cette application racine de passer ce qu'il faut comme configurations aux diverses librairies pour qu'elles puissent avoir
24
+ accès aux bons cids.
25
+
26
+ Si votre librairie, pour une raison quelconque, doit avoir accès aux Correlations Ids directement, il faut que l'application racine lui passe un "`Correlation Id Provider`", utilisant le service racine! Voir le projet [http-request] pour un exemple.
27
+
28
+
29
+ ## Utilisation
30
+
31
+ ### Configurations
32
+
33
+ Un code utilisant cette librarie doit premièrement la configurer en appellant la fonction
34
+ "`init(...)`" exportée par le fichier "`src/config/init.ts`".
35
+
36
+ La configuration "`loggerCreator`" est *requise* par cette librairie. Cela signifie qu'un code utilisant la librairie
37
+ (que ce soit du code d'un projet d'API ou d'une autre librairie) *doit* setter cette configuration *avant* que les composants
38
+ de la librairie ne soient utilisés.
39
+
40
+ Finalement, notez qu'une fonction "`isInited()`" est exportée et permet au code appelant de valider que la librairie a été
41
+ configurée correctement!
42
+
43
+ ### Mise en place
44
+
45
+ Il suffit d'ajouter le middleware `correlationIdMiddleware` dans une application `Express`. Par la suite, tout appel
46
+ à `correlationIdService.getId()` va retourner le bon correlation id du contexte courant. Cet id sera
47
+ sera reçu dans la requête, par le header "`X-Correlation-ID`" ou, s'il n'est pas présent, sera un nouvel id
48
+ généré.
49
+
50
+ Notez qu'un API démarré avec le générateur [generator-mtl-node-api]
51
+ aura déjà tout en place pour la gestion du correlation id.
52
+
53
+ Exemple :
54
+ ```typescript
55
+ import { correlationIdMiddleware } from "@villedemontreal/correlation-id";
56
+
57
+ const app = express();
58
+ app.use(correlationIdMiddleware);
59
+ ```
60
+
61
+ **Important!** : Si vous utilisez un middleware "`bodyParser`", assurez-vous que `correlationIdMiddleware` est enregistré
62
+ *après*, autrement une requête POST pourrait ne pas trouver le correlation id du context correctement!
63
+
64
+ ### Obtention du correlation id
65
+
66
+ Exemple :
67
+ ```typescript
68
+ import { correlationIdService, CorrelationId } from "@villedemontreal/correlation-id";
69
+
70
+ // Controller to update an account: PUT /accounts/:inum
71
+ public async update(req: express.Request, res: express.Response, next: express.NextFunction): Promise<void> {
72
+
73
+ // Get Correlation ID
74
+ let cid: CorrelationId = correlationIdService.getId();
75
+ console.log(cid);
76
+ }
77
+ ```
78
+
79
+ # Builder le projet
80
+
81
+ **Note**: Sur Linux/Mac assurz-vous que le fichier `run` est exécutable. Autrement, lancez `chmod +x ./run`.
82
+
83
+ Pour lancer le build :
84
+
85
+ - > `run compile` ou `./run compile` (sur Linux/Mac)
86
+
87
+ Pour lancer les tests :
88
+
89
+ - > `run test` ou `./run test` (sur Linux/Mac)
90
+
91
+ # Mode Watch
92
+
93
+ Lors du développement, il est possible de lancer `run watch` (ou `./run watch` sur Linux/mac) dans un terminal
94
+ externe pour démarrer la compilation incrémentale. Il est alors possible de lancer certaines _launch configuration_
95
+ comme `Debug current tests file - fast` dans VsCode et ainsi déboguer le fichier de tests présentement ouvert sans
96
+ avoir à (re)compiler au préalable (la compilation incrémentale s'en sera chargé).
97
+
98
+ Notez que, par défaut, des _notifications desktop_ sont activées pour indiquer visuellement si la compilation
99
+ incrémentale est un succès ou si une erreur a été trouvée. Vous pouvez désactiver ces notifications en utilisant
100
+ `run watch --dn` (`d`isable `n`otifications).
101
+
102
+ # Déboguer le projet
103
+
104
+ Trois "_launch configurations_" sont founies pour déboguer le projet dans VSCode :
105
+
106
+ - "`Debug all tests`", la launch configuration par défaut. Lance les tests en mode debug. Vous pouvez mettre
107
+ des breakpoints et ils seront respectés.
108
+
109
+ - "`Debug a test file`". Lance _un_ fichier de tests en mode debug. Vous pouvez mettre
110
+ des breakpoints et ils seront respectés. Pour changer le fichier de tests à être exécuté, vous devez modifier la ligne appropriée dans le fichier "`.vscode/launch.json`".
111
+
112
+ - "`Debug current tests file`". Lance le fichier de tests _présentement ouvert_ dans VSCode en mode debug. Effectue la compîlation au préalable.
113
+
114
+ - "`Debug current tests file - fast`". Lance le fichier de tests _présentement ouvert_ dans VSCode en mode debug. Aucune compilation
115
+ n'est effectuée au préalable. Cette launch configuration doit être utilisée lorsque la compilation incrémentale roule (voir la section "`Mode Watch`" plus haut)
116
+
117
+ # Aide / Contributions
118
+
119
+ Notez que les contributions sous forme de pull requests sont bienvenues.
@@ -0,0 +1,16 @@
1
+ import { ILogger } from '@villedemontreal/logger';
2
+ /**
3
+ * Http Client Config
4
+ */
5
+ export declare class Configs {
6
+ private loggerCreatorVar;
7
+ /**
8
+ * Sets the Logger creator.
9
+ */
10
+ setLoggerCreator(loggerCreator: (name: string) => ILogger): void;
11
+ /**
12
+ * The Logger creator
13
+ */
14
+ get loggerCreator(): (name: string) => ILogger;
15
+ }
16
+ export declare let configs: Configs;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configs = exports.Configs = void 0;
4
+ /**
5
+ * Http Client Config
6
+ */
7
+ class Configs {
8
+ /**
9
+ * Sets the Logger creator.
10
+ */
11
+ setLoggerCreator(loggerCreator) {
12
+ this.loggerCreatorVar = loggerCreator;
13
+ }
14
+ /**
15
+ * The Logger creator
16
+ */
17
+ get loggerCreator() {
18
+ if (!this.loggerCreatorVar) {
19
+ throw new Error(`The Logger Creator HAS to be set as a configuration! Please call the init(...) fonction first.`);
20
+ }
21
+ return this.loggerCreatorVar;
22
+ }
23
+ }
24
+ exports.Configs = Configs;
25
+ exports.configs = new Configs();
26
+ //# sourceMappingURL=configs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configs.js","sourceRoot":"","sources":["../../../src/config/configs.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACH,MAAa,OAAO;IAGlB;;OAEG;IACI,gBAAgB,CAAC,aAAwC;QAC9D,IAAI,CAAC,gBAAgB,GAAG,aAAa,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,IAAI,aAAa;QACf,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;SACnH;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAnBD,0BAmBC;AACU,QAAA,OAAO,GAAY,IAAI,OAAO,EAAE,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Library constants
3
+ */
4
+ export declare class Constants {
5
+ /**
6
+ * The library root. When this library is used
7
+ * as a dependency in a project, the "libRoot"
8
+ * will be the path to the dependency folder,
9
+ * inside the "node_modules".
10
+ */
11
+ libRoot: string;
12
+ /**
13
+ * The app root. When this library is used
14
+ * as a dependency in a project, the "appRoot"
15
+ * will be the path to the root project!
16
+ */
17
+ appRoot: string;
18
+ constructor();
19
+ /**
20
+ * Extra values that we can add to the original Express request.
21
+ */
22
+ get requestExtraVariables(): {
23
+ cidReceivedInRequest: string;
24
+ cidNew: string;
25
+ };
26
+ }
27
+ export declare let constants: Constants;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.constants = exports.Constants = void 0;
4
+ const app_root_path_1 = require("app-root-path");
5
+ const path = require("path");
6
+ /**
7
+ * Library constants
8
+ */
9
+ class Constants {
10
+ constructor() {
11
+ // From the "dist/src/config" folder
12
+ this.libRoot = path.normalize(__dirname + '/../../..');
13
+ this.appRoot = app_root_path_1.path;
14
+ }
15
+ /**
16
+ * Extra values that we can add to the original Express request.
17
+ */
18
+ get requestExtraVariables() {
19
+ return {
20
+ cidReceivedInRequest: '_cidReceivedInRequest',
21
+ cidNew: '_cidNew'
22
+ };
23
+ }
24
+ }
25
+ exports.Constants = Constants;
26
+ exports.constants = new Constants();
27
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/config/constants.ts"],"names":[],"mappings":";;;AAAA,iDAAgD;AAChD,6BAA6B;AAE7B;;GAEG;AACH,MAAa,SAAS;IAgBpB;QACE,oCAAoC;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,GAAG,WAAW,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,GAAG,oBAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,IAAI,qBAAqB;QACvB,OAAO;YACL,oBAAoB,EAAE,uBAAuB;YAC7C,MAAM,EAAE,SAAS;SAClB,CAAC;IACJ,CAAC;CACF;AA/BD,8BA+BC;AAEU,QAAA,SAAS,GAAc,IAAI,SAAS,EAAE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { ILogger } from '@villedemontreal/logger';
2
+ /**
3
+ * Inits the library.
4
+ */
5
+ export declare function init(loggerCreator: (name: string) => ILogger): void;
6
+ /**
7
+ * Is the library properly initialized?
8
+ *
9
+ * This function MUST be named "isInited()"!
10
+ * Code using this library may loop over all its "@villemontreal"
11
+ * dependencies and, if one of those exports a "isInited" fonction,
12
+ * it will enforce that the lib has been properly initialized before
13
+ * starting...
14
+ */
15
+ export declare function isInited(): boolean;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isInited = exports.init = void 0;
4
+ const configs_1 = require("./configs");
5
+ let libIsInited = false;
6
+ /**
7
+ * Inits the library.
8
+ */
9
+ function init(loggerCreator) {
10
+ if (!loggerCreator) {
11
+ throw new Error(`The Logger Creator is required.`);
12
+ }
13
+ configs_1.configs.setLoggerCreator(loggerCreator);
14
+ // ==========================================
15
+ // Set as being "properly initialized".
16
+ // At the very end of the "init()" function!
17
+ // ==========================================
18
+ libIsInited = true;
19
+ }
20
+ exports.init = init;
21
+ /**
22
+ * Is the library properly initialized?
23
+ *
24
+ * This function MUST be named "isInited()"!
25
+ * Code using this library may loop over all its "@villemontreal"
26
+ * dependencies and, if one of those exports a "isInited" fonction,
27
+ * it will enforce that the lib has been properly initialized before
28
+ * starting...
29
+ */
30
+ function isInited() {
31
+ return libIsInited;
32
+ }
33
+ exports.isInited = isInited;
34
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/config/init.ts"],"names":[],"mappings":";;;AACA,uCAAoC;AAEpC,IAAI,WAAW,GAAY,KAAK,CAAC;AAEjC;;GAEG;AACH,SAAgB,IAAI,CAAC,aAAwC;IAC3D,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;KACpD;IACD,iBAAO,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IAExC,6CAA6C;IAC7C,uCAAuC;IACvC,4CAA4C;IAC5C,6CAA6C;IAC7C,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAXD,oBAWC;AAED;;;;;;;;GAQG;AACH,SAAgB,QAAQ;IACtB,OAAO,WAAW,CAAC;AACrB,CAAC;AAFD,4BAEC"}
@@ -0,0 +1,3 @@
1
+ export * from './services/correlationIdService';
2
+ export * from './middleware/correlationIdMiddleware';
3
+ export * from './config/init';
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./services/correlationIdService"), exports);
18
+ __exportStar(require("./middleware/correlationIdMiddleware"), exports);
19
+ // ==========================================
20
+ // We do not export the configs instance itself,
21
+ // only the "init()" method, so we can define
22
+ // required parameters.
23
+ // ==========================================
24
+ __exportStar(require("./config/init"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kEAAgD;AAChD,uEAAqD;AAErD,6CAA6C;AAC7C,gDAAgD;AAChD,6CAA6C;AAC7C,uBAAuB;AACvB,6CAA6C;AAC7C,gDAA8B"}
@@ -0,0 +1,8 @@
1
+ import * as express from 'express';
2
+ /**
3
+ * Correlation ID Middleware
4
+ *
5
+ * @param filter a filter which is going to be called with the request to see if a
6
+ * colleration id scope must be managed or not.
7
+ */
8
+ export declare let createCorrelationIdMiddleware: (filter?: (req: express.Request) => boolean) => (req: express.Request, res: express.Response, next: express.NextFunction) => Promise<void>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCorrelationIdMiddleware = void 0;
4
+ const http_header_fields_typed_1 = require("http-header-fields-typed");
5
+ const constants_1 = require("../config/constants");
6
+ const correlationIdService_1 = require("../services/correlationIdService");
7
+ /**
8
+ * Correlation ID Middleware
9
+ *
10
+ * @param filter a filter which is going to be called with the request to see if a
11
+ * colleration id scope must be managed or not.
12
+ */
13
+ let createCorrelationIdMiddleware = (filter) => {
14
+ const correlationIdMiddleware = (req, res, next) => {
15
+ if (filter && !filter(req)) {
16
+ next();
17
+ }
18
+ else {
19
+ // ==========================================
20
+ // If a Correlation ID (cid) exists in the request
21
+ // it will be used. Otherwise, a new one is created.
22
+ //
23
+ // We add the cid to the response!
24
+ // ==========================================
25
+ let correlationId = req.get(http_header_fields_typed_1.default.X_CORRELATION_ID);
26
+ if (!correlationId) {
27
+ correlationId = correlationIdService_1.correlationIdService.createNewId();
28
+ req[constants_1.constants.requestExtraVariables.cidNew] = correlationId;
29
+ }
30
+ else {
31
+ req[constants_1.constants.requestExtraVariables.cidReceivedInRequest] = correlationId;
32
+ }
33
+ if (!res.headersSent) {
34
+ res.set(http_header_fields_typed_1.default.X_CORRELATION_ID, correlationId);
35
+ }
36
+ correlationIdService_1.correlationIdService.withId(next, correlationId);
37
+ }
38
+ return null;
39
+ };
40
+ return correlationIdMiddleware;
41
+ };
42
+ exports.createCorrelationIdMiddleware = createCorrelationIdMiddleware;
43
+ //# sourceMappingURL=correlationIdMiddleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"correlationIdMiddleware.js","sourceRoot":"","sources":["../../../src/middleware/correlationIdMiddleware.ts"],"names":[],"mappings":";;;AACA,uEAA6D;AAC7D,mDAAgD;AAChD,2EAAwE;AAExE;;;;;GAKG;AACI,IAAI,6BAA6B,GAAG,CACzC,MAA0C,EACoD,EAAE;IAChG,MAAM,uBAAuB,GAAG,CAC9B,GAAoB,EACpB,GAAqB,EACrB,IAA0B,EACX,EAAE;QACjB,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YAC1B,IAAI,EAAE,CAAC;SACR;aAAM;YACL,6CAA6C;YAC7C,kDAAkD;YAClD,oDAAoD;YACpD,EAAE;YACF,kCAAkC;YAClC,6CAA6C;YAC7C,IAAI,aAAa,GAAG,GAAG,CAAC,GAAG,CAAC,kCAAqB,CAAC,gBAAgB,CAAC,CAAC;YACpE,IAAI,CAAC,aAAa,EAAE;gBAClB,aAAa,GAAG,2CAAoB,CAAC,WAAW,EAAE,CAAC;gBACnD,GAAG,CAAC,qBAAS,CAAC,qBAAqB,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC;aAC7D;iBAAM;gBACL,GAAG,CAAC,qBAAS,CAAC,qBAAqB,CAAC,oBAAoB,CAAC,GAAG,aAAa,CAAC;aAC3E;YACD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE;gBACpB,GAAG,CAAC,GAAG,CAAC,kCAAqB,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;aAChE;YACD,2CAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;SAClD;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IAEF,OAAO,uBAAuB,CAAC;AACjC,CAAC,CAAC;AAjCS,QAAA,6BAA6B,iCAiCtC"}