@villedemontreal/general-utils 5.17.5 → 5.18.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 (102) hide show
  1. package/dist/config/configs.d.ts +1 -0
  2. package/dist/config/configs.d.ts.map +1 -0
  3. package/dist/config/configs.js +1 -24
  4. package/dist/config/configs.js.map +1 -1
  5. package/dist/src/apiError.d.ts +1 -0
  6. package/dist/src/apiError.d.ts.map +1 -0
  7. package/dist/src/apiError.js +1 -24
  8. package/dist/src/apiError.js.map +1 -1
  9. package/dist/src/apiError.test.d.ts +1 -0
  10. package/dist/src/apiError.test.d.ts.map +1 -0
  11. package/dist/src/apiError.test.js +32 -41
  12. package/dist/src/apiError.test.js.map +1 -1
  13. package/dist/src/apiErrorBuilder.d.ts +1 -0
  14. package/dist/src/apiErrorBuilder.d.ts.map +1 -0
  15. package/dist/src/apiErrorBuilder.js +1 -24
  16. package/dist/src/apiErrorBuilder.js.map +1 -1
  17. package/dist/src/collectionUtils.d.ts +1 -0
  18. package/dist/src/collectionUtils.d.ts.map +1 -0
  19. package/dist/src/collectionUtils.js +1 -24
  20. package/dist/src/collectionUtils.js.map +1 -1
  21. package/dist/src/collectionUtils.test.d.ts +1 -0
  22. package/dist/src/collectionUtils.test.d.ts.map +1 -0
  23. package/dist/src/collectionUtils.test.js +1 -24
  24. package/dist/src/collectionUtils.test.js.map +1 -1
  25. package/dist/src/config/constants.d.ts +2 -0
  26. package/dist/src/config/constants.d.ts.map +1 -0
  27. package/dist/src/config/constants.js +15 -24
  28. package/dist/src/config/constants.js.map +1 -1
  29. package/dist/src/config/globalConstants.d.ts +1 -0
  30. package/dist/src/config/globalConstants.d.ts.map +1 -0
  31. package/dist/src/dateUtils.d.ts +1 -0
  32. package/dist/src/dateUtils.d.ts.map +1 -0
  33. package/dist/src/dateUtils.js +14 -17
  34. package/dist/src/dateUtils.js.map +1 -1
  35. package/dist/src/dateUtils.test.d.ts +1 -0
  36. package/dist/src/dateUtils.test.d.ts.map +1 -0
  37. package/dist/src/dateUtils.test.js +8 -11
  38. package/dist/src/dateUtils.test.js.map +1 -1
  39. package/dist/src/index.d.ts +1 -0
  40. package/dist/src/index.d.ts.map +1 -0
  41. package/dist/src/logLevel.d.ts +1 -0
  42. package/dist/src/logLevel.d.ts.map +1 -0
  43. package/dist/src/logLevel.js +13 -3
  44. package/dist/src/logLevel.js.map +1 -1
  45. package/dist/src/orderBy.d.ts +1 -0
  46. package/dist/src/orderBy.d.ts.map +1 -0
  47. package/dist/src/orderBy.js +1 -24
  48. package/dist/src/orderBy.js.map +1 -1
  49. package/dist/src/pagination.d.ts +1 -0
  50. package/dist/src/pagination.d.ts.map +1 -0
  51. package/dist/src/pagination.test.d.ts +1 -0
  52. package/dist/src/pagination.test.d.ts.map +1 -0
  53. package/dist/src/pagination.test.js +2 -11
  54. package/dist/src/pagination.test.js.map +1 -1
  55. package/dist/src/stringUtils.d.ts +1 -0
  56. package/dist/src/stringUtils.d.ts.map +1 -0
  57. package/dist/src/stringUtils.js +1 -24
  58. package/dist/src/stringUtils.js.map +1 -1
  59. package/dist/src/stringUtils.test.d.ts +1 -0
  60. package/dist/src/stringUtils.test.d.ts.map +1 -0
  61. package/dist/src/timer.d.ts +1 -0
  62. package/dist/src/timer.d.ts.map +1 -0
  63. package/dist/src/timer.js +1 -24
  64. package/dist/src/timer.js.map +1 -1
  65. package/dist/src/timer.test.d.ts +1 -0
  66. package/dist/src/timer.test.d.ts.map +1 -0
  67. package/dist/src/timer.test.js +32 -47
  68. package/dist/src/timer.test.js.map +1 -1
  69. package/dist/src/utils.d.ts +1 -0
  70. package/dist/src/utils.d.ts.map +1 -0
  71. package/dist/src/utils.js +109 -158
  72. package/dist/src/utils.js.map +1 -1
  73. package/dist/src/utils.test.d.ts +1 -0
  74. package/dist/src/utils.test.d.ts.map +1 -0
  75. package/dist/src/utils.test.js +166 -201
  76. package/dist/src/utils.test.js.map +1 -1
  77. package/dist/test-data/test_throwNotManaged/962a8539-5522-4e44-aa9c-32475e5e537e.d.ts +2 -0
  78. package/dist/test-data/test_throwNotManaged/962a8539-5522-4e44-aa9c-32475e5e537e.d.ts.map +1 -0
  79. package/dist/test-data/test_throwNotManaged/962a8539-5522-4e44-aa9c-32475e5e537e.js +13 -0
  80. package/dist/test-data/test_throwNotManaged/962a8539-5522-4e44-aa9c-32475e5e537e.js.map +1 -0
  81. package/dist/tests-resources/exec/execTest.d.ts +1 -0
  82. package/dist/tests-resources/exec/execTest.d.ts.map +1 -0
  83. package/dist/tests-resources/exec/execTest.js +2 -11
  84. package/dist/tests-resources/exec/execTest.js.map +1 -1
  85. package/dist/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +27 -26
  87. package/src/collectionUtils.ts +1 -1
  88. package/src/config/constants.ts +16 -1
  89. package/src/dateUtils.test.ts +5 -3
  90. package/src/dateUtils.ts +6 -7
  91. package/src/logLevel.ts +13 -3
  92. package/src/utils.test.ts +4 -0
  93. package/src/utils.ts +16 -16
  94. package/dist/scripts/index.d.ts +0 -2
  95. package/dist/scripts/index.js +0 -14
  96. package/dist/scripts/index.js.map +0 -1
  97. package/dist/scripts/lint.d.ts +0 -6
  98. package/dist/scripts/lint.js +0 -31
  99. package/dist/scripts/lint.js.map +0 -1
  100. package/dist/scripts/lintFix.d.ts +0 -6
  101. package/dist/scripts/lintFix.js +0 -40
  102. package/dist/scripts/lintFix.js.map +0 -1
@@ -1,5 +1,6 @@
1
- import { path as appRoot } from 'app-root-path';
1
+ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
+ import { path as appRoot } from 'app-root-path';
3
4
 
4
5
  /**
5
6
  * Library constants
@@ -32,6 +33,20 @@ export class Constants {
32
33
  get testDataDirPath() {
33
34
  return this.libRoot + '/test-data';
34
35
  }
36
+
37
+ public findModulePath(subPath: string): string {
38
+ let current = this.libRoot;
39
+ let counter = 0;
40
+ while (counter < 10 && current !== '/' && fs.existsSync(current)) {
41
+ const p = path.join(current, subPath);
42
+ if (fs.existsSync(p)) {
43
+ return path.normalize(p);
44
+ }
45
+ current = path.normalize(path.join(current, '..'));
46
+ counter += 1;
47
+ }
48
+ throw new Error(`Could not find module "${subPath}"`);
49
+ }
35
50
  }
36
51
 
37
52
  export const constants: Constants = new Constants();
@@ -1,6 +1,6 @@
1
1
  import { assert } from 'chai';
2
- import _ from 'lodash';
3
- import moment from 'moment';
2
+ import * as _ from 'lodash';
3
+ import * as moment from 'moment';
4
4
  import { getValueDescription, getValueDescriptionWithType, utils } from '.';
5
5
  import { getCartesianProduct } from './collectionUtils';
6
6
  import {
@@ -177,7 +177,9 @@ describe('Date Utility', () => {
177
177
  for (const entry of expectations) {
178
178
  const value = entry[0];
179
179
  const expectedResult = entry[1];
180
- const valueDescription = `[${getValueDescriptionWithType(value[0])}, ${getValueDescriptionWithType(value[1])}]`;
180
+ const valueDescription = `[${getValueDescriptionWithType(
181
+ value[0],
182
+ )}, ${getValueDescriptionWithType(value[1])}]`;
181
183
  it(`should support ${valueDescription}`, () => {
182
184
  assert.deepEqual(getSafeDateRange(value), expectedResult);
183
185
  });
package/src/dateUtils.ts CHANGED
@@ -1,9 +1,8 @@
1
- import _ from 'lodash';
2
1
  import { DateTime, Zone } from 'luxon';
3
- import moment from 'moment';
4
- // tslint:disable-next-line:no-duplicate-imports
2
+ import * as moment from 'moment';
5
3
  import { Moment } from 'moment';
6
4
  import { getValueDescription, utils } from '.';
5
+ import { isDate, isNil } from 'lodash';
7
6
 
8
7
  export function isDateEqual(value: DateDefinition, expectedDate: DateDefinition) {
9
8
  const _moment: Moment = moment(value);
@@ -231,11 +230,11 @@ export function startOfDay(
231
230
  isoDate: Date | string,
232
231
  timezone: string | Zone = 'America/Montreal',
233
232
  ): Date {
234
- if (_.isNil(isoDate)) {
233
+ if (isNil(isoDate)) {
235
234
  return isoDate;
236
235
  }
237
236
 
238
- let luxonDate = DateTime.fromISO(_.isDate(isoDate) ? isoDate.toISOString() : isoDate);
237
+ let luxonDate = DateTime.fromISO(isDate(isoDate) ? isoDate.toISOString() : isoDate);
239
238
  if (!luxonDate.isValid) {
240
239
  throw new Error(`Invalid ISO date ${JSON.stringify(isoDate)} : ${luxonDate.invalidReason}`);
241
240
  }
@@ -262,11 +261,11 @@ export function endOfDay(
262
261
  isoDate: Date | string,
263
262
  timezone: string | Zone = 'America/Montreal',
264
263
  ): Date {
265
- if (_.isNil(isoDate)) {
264
+ if (isNil(isoDate)) {
266
265
  return isoDate;
267
266
  }
268
267
 
269
- let luxonDate = DateTime.fromISO(_.isDate(isoDate) ? isoDate.toISOString() : isoDate);
268
+ let luxonDate = DateTime.fromISO(isDate(isoDate) ? isoDate.toISOString() : isoDate);
270
269
  if (!luxonDate.isValid) {
271
270
  throw new Error(`Invalid ISO date ${JSON.stringify(isoDate)} : ${luxonDate.invalidReason}`);
272
271
  }
package/src/logLevel.ts CHANGED
@@ -24,10 +24,20 @@ export enum LogLevel {
24
24
  * LogLevel enum value.
25
25
  */
26
26
  export const logLevelFromString = (levelStr: string): LogLevel => {
27
- if (levelStr) {
28
- return LogLevel[levelStr.toUpperCase()];
27
+ switch ((levelStr || '').toUpperCase()) {
28
+ case 'DEBUG':
29
+ return LogLevel.DEBUG;
30
+ case 'TRACE':
31
+ return LogLevel.TRACE;
32
+ case 'ERROR':
33
+ return LogLevel.ERROR;
34
+ case 'INFO':
35
+ return LogLevel.INFO;
36
+ case 'WARNING':
37
+ return LogLevel.WARNING;
38
+ default:
39
+ return LogLevel.DEBUG;
29
40
  }
30
- return undefined;
31
41
  };
32
42
 
33
43
  /**
package/src/utils.test.ts CHANGED
@@ -16,6 +16,10 @@ import { ExecError, utils, Utils } from './utils';
16
16
  // @see https://github.com/mochajs/mocha/issues/2018
17
17
  // tslint:disable-next-line:only-arrow-functions ter-prefer-arrow-callback
18
18
  describe("App's utilities functions", function () {
19
+ this.beforeAll(() => {
20
+ constants.appRoot = constants.libRoot; // because our lib is within a monorepo
21
+ });
22
+
19
23
  // ==========================================
20
24
  // tsc()
21
25
  // ==========================================
package/src/utils.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { spawn, StdioOptions } from 'child_process';
2
2
  import * as fs from 'fs';
3
- import getPort from 'get-port';
4
- import _ from 'lodash';
3
+ import * as getPort from 'get-port';
5
4
  import * as pathUtils from 'path';
6
5
  import { rimraf } from 'rimraf';
7
6
  import * as tsconfig from 'tsconfig-extends';
8
7
  import { constants } from './config/constants';
8
+ import { isArray, isDate, isEqual, isFunction, isNil, isObject, isString, trimEnd } from 'lodash';
9
9
 
10
10
  /**
11
11
  * General utilities
@@ -158,7 +158,7 @@ export class Utils {
158
158
  pathClean = pathUtils.normalize(pathClean);
159
159
 
160
160
  pathClean = pathClean.replace(/\\/g, '/');
161
- pathClean = _.trimEnd(pathClean, '/ ');
161
+ pathClean = trimEnd(pathClean, '/ ');
162
162
 
163
163
  return (pathClean.match(/\//g) || []).length > 1;
164
164
  }
@@ -268,11 +268,12 @@ export class Utils {
268
268
  if (!this.tscCompilerOptionsParams) {
269
269
  this.tscCompilerOptionsParams = [];
270
270
  const compilerOptions = tsconfig.load_file_sync(constants.appRoot + '/tsconfig.json');
271
+
271
272
  for (const key of Object.keys(compilerOptions)) {
272
273
  // ==========================================
273
- // TS6064: Option 'plugins' can only be specified in 'tsconfig.json' file.
274
+ // TS6064: Options 'plugins', 'composite' can only be specified in 'tsconfig.json' file.
274
275
  // ==========================================
275
- if (key === 'plugins') {
276
+ if (['plugins', 'composite'].includes(key)) {
276
277
  continue;
277
278
  }
278
279
 
@@ -306,9 +307,8 @@ export class Utils {
306
307
  }
307
308
 
308
309
  const cmd = 'node';
309
- const args = [constants.libRoot + '/node_modules/typescript/lib/tsc.js']
310
- .concat(this.tscCompilerOptions)
311
- .concat(files);
310
+ const tscCmd = constants.findModulePath('node_modules/typescript/lib/tsc.js');
311
+ const args = [tscCmd].concat(this.tscCompilerOptions).concat(files);
312
312
 
313
313
  await this.execPromisified(cmd, args);
314
314
  }
@@ -362,13 +362,13 @@ export class Utils {
362
362
  public dateTransformer = (value: any): Date => {
363
363
  let date: Date;
364
364
 
365
- if (_.isNil(value)) {
365
+ if (isNil(value)) {
366
366
  return null;
367
367
  }
368
368
 
369
- if (_.isDate(value)) {
369
+ if (isDate(value)) {
370
370
  date = value;
371
- } else if (!_.isString(value) || utils.isBlank(value)) {
371
+ } else if (!isString(value) || utils.isBlank(value)) {
372
372
  // ==========================================
373
373
  // Makes sure it's an invalid date!
374
374
  // Because by default, true and 123 are accepted,
@@ -406,7 +406,7 @@ export class Utils {
406
406
  if (!val) {
407
407
  return false;
408
408
  }
409
- return _.isObject(val) && !_.isArray(val) && !_.isDate(val) && !_.isFunction(val);
409
+ return isObject(val) && !isArray(val) && !isDate(val) && !isFunction(val);
410
410
  };
411
411
 
412
412
  /**
@@ -415,12 +415,12 @@ export class Utils {
415
415
  * strictly equals to the specified "value".
416
416
  */
417
417
  public arrayContainsObjectWithKeyEqualsTo = (array: any[], key: string, value: any): boolean => {
418
- if (!array || !_.isArray(array) || array.length < 1) {
418
+ if (!array || !isArray(array) || array.length < 1) {
419
419
  return false;
420
420
  }
421
421
 
422
422
  for (const obj of array) {
423
- if (this.isObjectStrict(obj) && _.isEqual(obj[key], value)) {
423
+ if (this.isObjectStrict(obj) && isEqual(obj[key], value)) {
424
424
  return true;
425
425
  }
426
426
  }
@@ -499,7 +499,7 @@ export class Utils {
499
499
  const optionsClean = options ?? {};
500
500
  optionsClean.useShellOption = optionsClean.useShellOption ?? true;
501
501
  optionsClean.successExitCodes = optionsClean.successExitCodes
502
- ? _.isArray(optionsClean.successExitCodes)
502
+ ? isArray(optionsClean.successExitCodes)
503
503
  ? optionsClean.successExitCodes
504
504
  : [optionsClean.successExitCodes]
505
505
  : [0];
@@ -575,7 +575,7 @@ export function getValueDescription(value: any): string {
575
575
  }
576
576
 
577
577
  export function getValueDescriptionWithType(value: any): string {
578
- const valueType = _.isObject(value) ? value.constructor.name : typeof value;
578
+ const valueType = isObject(value) ? value.constructor.name : typeof value;
579
579
  return getValueDescription(value) + ` (${valueType})`;
580
580
  }
581
581
 
@@ -1,2 +0,0 @@
1
- export { LintScript } from './lint';
2
- export { LintFixScript } from './lintFix';
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LintFixScript = exports.LintScript = void 0;
4
- // ==========================================
5
- // All scripts must be included here!
6
- //
7
- // The scripting library uses this index to quickly
8
- // find all the scripts available in the application.
9
- // ==========================================
10
- var lint_1 = require("./lint");
11
- Object.defineProperty(exports, "LintScript", { enumerable: true, get: function () { return lint_1.LintScript; } });
12
- var lintFix_1 = require("./lintFix");
13
- Object.defineProperty(exports, "LintFixScript", { enumerable: true, get: function () { return lintFix_1.LintFixScript; } });
14
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../scripts/index.ts"],"names":[],"mappings":";;;AAAA,6CAA6C;AAC7C,qCAAqC;AACrC,EAAE;AACF,mDAAmD;AACnD,qDAAqD;AACrD,6CAA6C;AAC7C,+BAAoC;AAA3B,kGAAA,UAAU,OAAA;AACnB,qCAA0C;AAAjC,wGAAA,aAAa,OAAA"}
@@ -1,6 +0,0 @@
1
- import { ScriptBase } from '@villedemontreal/scripting/dist/src';
2
- export declare class LintScript extends ScriptBase {
3
- get name(): string;
4
- get description(): string;
5
- protected main(): Promise<void>;
6
- }
@@ -1,31 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.LintScript = void 0;
13
- const src_1 = require("@villedemontreal/scripting/dist/src");
14
- const path_1 = require("path");
15
- const configs_1 = require("../config/configs");
16
- class LintScript extends src_1.ScriptBase {
17
- get name() {
18
- return 'lint';
19
- }
20
- get description() {
21
- return `Run the ESLint validation (including ESLint and Prettier rules).`;
22
- }
23
- main() {
24
- return __awaiter(this, void 0, void 0, function* () {
25
- const projectRoot = (0, path_1.resolve)(`${configs_1.configs.root}/..`);
26
- yield this.invokeShellCommand(`${projectRoot}/node_modules/.bin/eslint`, [projectRoot]);
27
- });
28
- }
29
- }
30
- exports.LintScript = LintScript;
31
- //# sourceMappingURL=lint.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lint.js","sourceRoot":"","sources":["../../scripts/lint.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6DAAiE;AACjE,+BAA+B;AAC/B,+CAA4C;AAC5C,MAAa,UAAW,SAAQ,gBAAU;IACxC,IAAI,IAAI;QACN,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,kEAAkE,CAAC;IAC5E,CAAC;IAEe,IAAI;;YAClB,MAAM,WAAW,GAAG,IAAA,cAAO,EAAC,GAAG,iBAAO,CAAC,IAAI,KAAK,CAAC,CAAC;YAClD,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,WAAW,2BAA2B,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QAC1F,CAAC;KAAA;CACF;AAbD,gCAaC"}
@@ -1,6 +0,0 @@
1
- import { ScriptBase } from '@villedemontreal/scripting/dist/src';
2
- export declare class LintFixScript extends ScriptBase {
3
- get name(): string;
4
- get description(): string;
5
- protected main(): Promise<void>;
6
- }
@@ -1,40 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.LintFixScript = void 0;
13
- const src_1 = require("@villedemontreal/scripting/dist/src");
14
- const path_1 = require("path");
15
- const configs_1 = require("../config/configs");
16
- class LintFixScript extends src_1.ScriptBase {
17
- get name() {
18
- return 'lint-fix';
19
- }
20
- get description() {
21
- return `Fix the code using ESLint and Prettier rules).`;
22
- }
23
- main() {
24
- return __awaiter(this, void 0, void 0, function* () {
25
- const projectRoot = (0, path_1.resolve)(`${configs_1.configs.root}/..`);
26
- this.logger.info(`Fixing using Prettier rules`);
27
- yield this.invokeShellCommand(`${projectRoot}/node_modules/.bin/prettier`, [
28
- '--write',
29
- projectRoot,
30
- ]);
31
- this.logger.info(`Fixing using ESLint rules`);
32
- yield this.invokeShellCommand(`${projectRoot}/node_modules/.bin/eslint`, [
33
- '--fix',
34
- projectRoot,
35
- ]);
36
- });
37
- }
38
- }
39
- exports.LintFixScript = LintFixScript;
40
- //# sourceMappingURL=lintFix.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lintFix.js","sourceRoot":"","sources":["../../scripts/lintFix.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6DAAiE;AACjE,+BAA+B;AAC/B,+CAA4C;AAE5C,MAAa,aAAc,SAAQ,gBAAU;IAC3C,IAAI,IAAI;QACN,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,gDAAgD,CAAC;IAC1D,CAAC;IAEe,IAAI;;YAClB,MAAM,WAAW,GAAG,IAAA,cAAO,EAAC,GAAG,iBAAO,CAAC,IAAI,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YAChD,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,WAAW,6BAA6B,EAAE;gBACzE,SAAS;gBACT,WAAW;aACZ,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC9C,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,WAAW,2BAA2B,EAAE;gBACvE,OAAO;gBACP,WAAW;aACZ,CAAC,CAAC;QACL,CAAC;KAAA;CACF;AAvBD,sCAuBC"}