@memlab/cli 1.0.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 (198) hide show
  1. package/README.md +11 -0
  2. package/bin/memlab +14 -0
  3. package/dist/BaseCommand.d.ts +37 -0
  4. package/dist/BaseCommand.d.ts.map +1 -0
  5. package/dist/BaseCommand.js +132 -0
  6. package/dist/Dispatcher.d.ts +35 -0
  7. package/dist/Dispatcher.d.ts.map +1 -0
  8. package/dist/Dispatcher.js +205 -0
  9. package/dist/TypesThirdParty.d.ts +17 -0
  10. package/dist/TypesThirdParty.d.ts.map +1 -0
  11. package/dist/TypesThirdParty.js +10 -0
  12. package/dist/commands/CleanLoggerDataCommand.d.ts +20 -0
  13. package/dist/commands/CleanLoggerDataCommand.d.ts.map +1 -0
  14. package/dist/commands/CleanLoggerDataCommand.js +50 -0
  15. package/dist/commands/CleanRunDataCommand.d.ts +20 -0
  16. package/dist/commands/CleanRunDataCommand.d.ts.map +1 -0
  17. package/dist/commands/CleanRunDataCommand.js +48 -0
  18. package/dist/commands/InitDirectoryCommand.d.ts +20 -0
  19. package/dist/commands/InitDirectoryCommand.d.ts.map +1 -0
  20. package/dist/commands/InitDirectoryCommand.js +48 -0
  21. package/dist/commands/ListScenariosCommand.d.ts +17 -0
  22. package/dist/commands/ListScenariosCommand.d.ts.map +1 -0
  23. package/dist/commands/ListScenariosCommand.js +51 -0
  24. package/dist/commands/MemLabRunCommand.d.ts +20 -0
  25. package/dist/commands/MemLabRunCommand.d.ts.map +1 -0
  26. package/dist/commands/MemLabRunCommand.js +66 -0
  27. package/dist/commands/PrintSummaryCommand.d.ts +20 -0
  28. package/dist/commands/PrintSummaryCommand.d.ts.map +1 -0
  29. package/dist/commands/PrintSummaryCommand.js +55 -0
  30. package/dist/commands/ResetDirectoryCommand.d.ts +19 -0
  31. package/dist/commands/ResetDirectoryCommand.d.ts.map +1 -0
  32. package/dist/commands/ResetDirectoryCommand.js +46 -0
  33. package/dist/commands/RunMeasureCommand.d.ts +20 -0
  34. package/dist/commands/RunMeasureCommand.d.ts.map +1 -0
  35. package/dist/commands/RunMeasureCommand.js +82 -0
  36. package/dist/commands/WarmupAppCommand.d.ts +20 -0
  37. package/dist/commands/WarmupAppCommand.d.ts.map +1 -0
  38. package/dist/commands/WarmupAppCommand.js +65 -0
  39. package/dist/commands/heap/CheckLeakCommand.d.ts +21 -0
  40. package/dist/commands/heap/CheckLeakCommand.d.ts.map +1 -0
  41. package/dist/commands/heap/CheckLeakCommand.js +94 -0
  42. package/dist/commands/heap/GetRetainerTraceCommand.d.ts +21 -0
  43. package/dist/commands/heap/GetRetainerTraceCommand.d.ts.map +1 -0
  44. package/dist/commands/heap/GetRetainerTraceCommand.js +92 -0
  45. package/dist/commands/heap/HeapAnalysisCommand.d.ts +21 -0
  46. package/dist/commands/heap/HeapAnalysisCommand.d.ts.map +1 -0
  47. package/dist/commands/heap/HeapAnalysisCommand.js +98 -0
  48. package/dist/commands/heap/HeapAnalysisSubCommandWrapper.d.ts +23 -0
  49. package/dist/commands/heap/HeapAnalysisSubCommandWrapper.d.ts.map +1 -0
  50. package/dist/commands/heap/HeapAnalysisSubCommandWrapper.js +68 -0
  51. package/dist/commands/helper/HelperCommand.d.ts +37 -0
  52. package/dist/commands/helper/HelperCommand.d.ts.map +1 -0
  53. package/dist/commands/helper/HelperCommand.js +262 -0
  54. package/dist/commands/helper/lib/CommandOrder.d.ts +13 -0
  55. package/dist/commands/helper/lib/CommandOrder.d.ts.map +1 -0
  56. package/dist/commands/helper/lib/CommandOrder.js +42 -0
  57. package/dist/commands/helper/lib/Types.d.ts +16 -0
  58. package/dist/commands/helper/lib/Types.d.ts.map +1 -0
  59. package/dist/commands/helper/lib/Types.js +11 -0
  60. package/dist/commands/query/QueryDefaultWorkDirCommand.d.ts +20 -0
  61. package/dist/commands/query/QueryDefaultWorkDirCommand.d.ts.map +1 -0
  62. package/dist/commands/query/QueryDefaultWorkDirCommand.js +67 -0
  63. package/dist/commands/snapshot/CheckXvfbSupportCommand.d.ts +18 -0
  64. package/dist/commands/snapshot/CheckXvfbSupportCommand.d.ts.map +1 -0
  65. package/dist/commands/snapshot/CheckXvfbSupportCommand.js +55 -0
  66. package/dist/commands/snapshot/Snapshot.d.ts +11 -0
  67. package/dist/commands/snapshot/Snapshot.d.ts.map +1 -0
  68. package/dist/commands/snapshot/Snapshot.js +47 -0
  69. package/dist/commands/snapshot/TakeSnapshotCommand.d.ts +20 -0
  70. package/dist/commands/snapshot/TakeSnapshotCommand.d.ts.map +1 -0
  71. package/dist/commands/snapshot/TakeSnapshotCommand.js +80 -0
  72. package/dist/commands/snapshot/WarmupAndSnapshotCommand.d.ts +18 -0
  73. package/dist/commands/snapshot/WarmupAndSnapshotCommand.d.ts.map +1 -0
  74. package/dist/commands/snapshot/WarmupAndSnapshotCommand.js +49 -0
  75. package/dist/commands/test/BrowserTest.d.ts +11 -0
  76. package/dist/commands/test/BrowserTest.d.ts.map +1 -0
  77. package/dist/commands/test/BrowserTest.js +41 -0
  78. package/dist/commands/test/RunAllInteractionTestsCommand.d.ts +19 -0
  79. package/dist/commands/test/RunAllInteractionTestsCommand.d.ts.map +1 -0
  80. package/dist/commands/test/RunAllInteractionTestsCommand.js +71 -0
  81. package/dist/commands/test/RunInteractionTestCommand.d.ts +19 -0
  82. package/dist/commands/test/RunInteractionTestCommand.d.ts.map +1 -0
  83. package/dist/commands/test/RunInteractionTestCommand.js +75 -0
  84. package/dist/index.d.ts +11 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +26 -0
  87. package/dist/options/AppOption.d.ts +19 -0
  88. package/dist/options/AppOption.d.ts.map +1 -0
  89. package/dist/options/AppOption.js +42 -0
  90. package/dist/options/DebugOption.d.ts +18 -0
  91. package/dist/options/DebugOption.d.ts.map +1 -0
  92. package/dist/options/DebugOption.js +37 -0
  93. package/dist/options/DisableXvfbOption.d.ts +18 -0
  94. package/dist/options/DisableXvfbOption.d.ts.map +1 -0
  95. package/dist/options/DisableXvfbOption.js +37 -0
  96. package/dist/options/FullExecutionOption.d.ts +18 -0
  97. package/dist/options/FullExecutionOption.d.ts.map +1 -0
  98. package/dist/options/FullExecutionOption.js +37 -0
  99. package/dist/options/HeapNodeIdOption.d.ts +19 -0
  100. package/dist/options/HeapNodeIdOption.d.ts.map +1 -0
  101. package/dist/options/HeapNodeIdOption.js +46 -0
  102. package/dist/options/HelperOption.d.ts +19 -0
  103. package/dist/options/HelperOption.d.ts.map +1 -0
  104. package/dist/options/HelperOption.js +39 -0
  105. package/dist/options/InteractionOption.d.ts +19 -0
  106. package/dist/options/InteractionOption.d.ts.map +1 -0
  107. package/dist/options/InteractionOption.js +42 -0
  108. package/dist/options/NumberOfRunsOption.d.ts +20 -0
  109. package/dist/options/NumberOfRunsOption.d.ts.map +1 -0
  110. package/dist/options/NumberOfRunsOption.js +44 -0
  111. package/dist/options/RemoteBrowserDebugOption.d.ts +18 -0
  112. package/dist/options/RemoteBrowserDebugOption.d.ts.map +1 -0
  113. package/dist/options/RemoteBrowserDebugOption.js +37 -0
  114. package/dist/options/RunningModeOption.d.ts +19 -0
  115. package/dist/options/RunningModeOption.d.ts.map +1 -0
  116. package/dist/options/RunningModeOption.js +40 -0
  117. package/dist/options/ScenarioFileOption.d.ts +19 -0
  118. package/dist/options/ScenarioFileOption.d.ts.map +1 -0
  119. package/dist/options/ScenarioFileOption.js +44 -0
  120. package/dist/options/SetContinuousTestOption.d.ts +18 -0
  121. package/dist/options/SetContinuousTestOption.d.ts.map +1 -0
  122. package/dist/options/SetContinuousTestOption.js +37 -0
  123. package/dist/options/SetDeviceOption.d.ts +19 -0
  124. package/dist/options/SetDeviceOption.d.ts.map +1 -0
  125. package/dist/options/SetDeviceOption.js +46 -0
  126. package/dist/options/SetWorkingDirectoryOption.d.ts +20 -0
  127. package/dist/options/SetWorkingDirectoryOption.d.ts.map +1 -0
  128. package/dist/options/SetWorkingDirectoryOption.js +40 -0
  129. package/dist/options/SilentOption.d.ts +19 -0
  130. package/dist/options/SilentOption.d.ts.map +1 -0
  131. package/dist/options/SilentOption.js +40 -0
  132. package/dist/options/SkipExtraOperationOption.d.ts +18 -0
  133. package/dist/options/SkipExtraOperationOption.d.ts.map +1 -0
  134. package/dist/options/SkipExtraOperationOption.js +37 -0
  135. package/dist/options/SkipGCOption.d.ts +18 -0
  136. package/dist/options/SkipGCOption.d.ts.map +1 -0
  137. package/dist/options/SkipGCOption.js +37 -0
  138. package/dist/options/SkipScreenshotOption.d.ts +18 -0
  139. package/dist/options/SkipScreenshotOption.d.ts.map +1 -0
  140. package/dist/options/SkipScreenshotOption.js +37 -0
  141. package/dist/options/SkipScrollOption.d.ts +18 -0
  142. package/dist/options/SkipScrollOption.d.ts.map +1 -0
  143. package/dist/options/SkipScrollOption.js +37 -0
  144. package/dist/options/SkipSnapshotOption.d.ts +18 -0
  145. package/dist/options/SkipSnapshotOption.d.ts.map +1 -0
  146. package/dist/options/SkipSnapshotOption.js +37 -0
  147. package/dist/options/SkipWarmupOption.d.ts +18 -0
  148. package/dist/options/SkipWarmupOption.d.ts.map +1 -0
  149. package/dist/options/SkipWarmupOption.js +37 -0
  150. package/dist/options/VerboseOption.d.ts +19 -0
  151. package/dist/options/VerboseOption.d.ts.map +1 -0
  152. package/dist/options/VerboseOption.js +40 -0
  153. package/dist/options/heap/BaselineFileOption.d.ts +18 -0
  154. package/dist/options/heap/BaselineFileOption.d.ts.map +1 -0
  155. package/dist/options/heap/BaselineFileOption.js +53 -0
  156. package/dist/options/heap/FinalFileOption.d.ts +18 -0
  157. package/dist/options/heap/FinalFileOption.d.ts.map +1 -0
  158. package/dist/options/heap/FinalFileOption.js +53 -0
  159. package/dist/options/heap/JSEngineOption.d.ts +18 -0
  160. package/dist/options/heap/JSEngineOption.d.ts.map +1 -0
  161. package/dist/options/heap/JSEngineOption.js +46 -0
  162. package/dist/options/heap/LogTraceAsClusterOption.d.ts +18 -0
  163. package/dist/options/heap/LogTraceAsClusterOption.d.ts.map +1 -0
  164. package/dist/options/heap/LogTraceAsClusterOption.js +37 -0
  165. package/dist/options/heap/OversizeThresholdOption.d.ts +19 -0
  166. package/dist/options/heap/OversizeThresholdOption.d.ts.map +1 -0
  167. package/dist/options/heap/OversizeThresholdOption.js +45 -0
  168. package/dist/options/heap/SnapshotDirectoryOption.d.ts +18 -0
  169. package/dist/options/heap/SnapshotDirectoryOption.d.ts.map +1 -0
  170. package/dist/options/heap/SnapshotDirectoryOption.js +50 -0
  171. package/dist/options/heap/SnapshotFileOption.d.ts +18 -0
  172. package/dist/options/heap/SnapshotFileOption.d.ts.map +1 -0
  173. package/dist/options/heap/SnapshotFileOption.js +50 -0
  174. package/dist/options/heap/TargetFileOption.d.ts +18 -0
  175. package/dist/options/heap/TargetFileOption.d.ts.map +1 -0
  176. package/dist/options/heap/TargetFileOption.js +53 -0
  177. package/dist/options/heap/TraceAllObjectsOption.d.ts +18 -0
  178. package/dist/options/heap/TraceAllObjectsOption.d.ts.map +1 -0
  179. package/dist/options/heap/TraceAllObjectsOption.js +38 -0
  180. package/dist/options/heap/leak-filter/LeakFilterFileOption.d.ts +19 -0
  181. package/dist/options/heap/leak-filter/LeakFilterFileOption.d.ts.map +1 -0
  182. package/dist/options/heap/leak-filter/LeakFilterFileOption.js +41 -0
  183. package/dist/options/heap/leak-filter/examples/FilterLib.d.ts +12 -0
  184. package/dist/options/heap/leak-filter/examples/FilterLib.d.ts.map +1 -0
  185. package/dist/options/heap/leak-filter/examples/FilterLib.js +30 -0
  186. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-1.d.ts +13 -0
  187. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-1.d.ts.map +1 -0
  188. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-1.js +30 -0
  189. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-2.d.ts +16 -0
  190. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-2.d.ts.map +1 -0
  191. package/dist/options/heap/leak-filter/examples/dup-string-as-leak.example-2.js +28 -0
  192. package/dist/options/heap/leak-filter/examples/large-object-as-leak.example.d.ts +3 -0
  193. package/dist/options/heap/leak-filter/examples/large-object-as-leak.example.d.ts.map +1 -0
  194. package/dist/options/heap/leak-filter/examples/large-object-as-leak.example.js +13 -0
  195. package/dist/runner.d.ts +11 -0
  196. package/dist/runner.d.ts.map +1 -0
  197. package/dist/runner.js +38 -0
  198. package/package.json +59 -0
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # `@memlab/cli`
2
+
3
+ > TODO: description
4
+
5
+ ## Usage
6
+
7
+ ```
8
+ const cli = require('@memlab/cli');
9
+
10
+ // TODO: DEMONSTRATE API
11
+ ```
package/bin/memlab ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env -S node --expose-gc --max-old-space-size=4096
2
+
3
+ /**
4
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ *
9
+ * @emails oncall+ws_labs
10
+ * @format
11
+ */
12
+
13
+ var cli = require("@memlab/cli");
14
+ cli.run();
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { CLIOptions, Nullable } from '@memlab/core';
11
+ import { BaseOption } from '@memlab/core';
12
+ export declare enum CommandCategory {
13
+ COMMON = "COMMON",
14
+ DEV = "DEV",
15
+ MISC = "MISC"
16
+ }
17
+ declare abstract class Command {
18
+ getCommandName(): string;
19
+ private parentCommand;
20
+ setParentCommand(parent: BaseCommand): void;
21
+ getParentCommand(): Nullable<BaseCommand>;
22
+ getFullCommand(): string;
23
+ getFullOptionsFromPrerequisiteChain(): BaseOption[];
24
+ }
25
+ export default class BaseCommand extends Command {
26
+ getCommandName(): string;
27
+ getExamples(): string[];
28
+ getCategory(): CommandCategory;
29
+ getDescription(): string;
30
+ getPrerequisites(): BaseCommand[];
31
+ isInternalCommand(): boolean;
32
+ getOptions(): BaseOption[];
33
+ getSubCommands(): BaseCommand[];
34
+ run(_options: CLIOptions): Promise<void>;
35
+ }
36
+ export {};
37
+ //# sourceMappingURL=BaseCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseCommand.d.ts","sourceRoot":"","sources":["../src/BaseCommand.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAE,QAAQ,EAAC,MAAM,cAAc,CAAC;AACvD,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AAExC,oBAAY,eAAe;IACzB,MAAM,WAAW;IACjB,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;AAED,uBAAe,OAAO;IACpB,cAAc,IAAI,MAAM;IAUxB,OAAO,CAAC,aAAa,CAA+B;IAEpD,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAI3C,gBAAgB,IAAI,QAAQ,CAAC,WAAW,CAAC;IAIzC,cAAc,IAAI,MAAM;IAOxB,mCAAmC,IAAI,UAAU,EAAE;CAyBpD;AAED,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,OAAO;IAG9C,cAAc,IAAI,MAAM;IAOxB,WAAW,IAAI,MAAM,EAAE;IAMvB,WAAW,IAAI,eAAe;IAM9B,cAAc,IAAI,MAAM;IAOxB,gBAAgB,IAAI,WAAW,EAAE;IAKjC,iBAAiB,IAAI,OAAO;IAK5B,UAAU,IAAI,UAAU,EAAE;IAQ1B,cAAc,IAAI,WAAW,EAAE;IAOzB,GAAG,CAAC,QAAQ,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAI/C"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.CommandCategory = void 0;
22
+ var CommandCategory;
23
+ (function (CommandCategory) {
24
+ CommandCategory["COMMON"] = "COMMON";
25
+ CommandCategory["DEV"] = "DEV";
26
+ CommandCategory["MISC"] = "MISC";
27
+ })(CommandCategory = exports.CommandCategory || (exports.CommandCategory = {}));
28
+ class Command {
29
+ constructor() {
30
+ // If you are trying to add a new CLI command in MemLab,
31
+ // DO NOT OVERRIDE any property or method in below in this class.
32
+ // These methods are intended for internal orchestration
33
+ // purposes. All commands should extend BaseCommand,
34
+ // which contains the overridable hooks.
35
+ this.parentCommand = null;
36
+ }
37
+ getCommandName() {
38
+ const className = this.constructor.name;
39
+ throw new Error(`${className}.getCommandName is not implemented`);
40
+ }
41
+ setParentCommand(parent) {
42
+ this.parentCommand = parent;
43
+ }
44
+ getParentCommand() {
45
+ return this.parentCommand;
46
+ }
47
+ getFullCommand() {
48
+ const prefix = this.parentCommand
49
+ ? this.parentCommand.getFullCommand() + ' '
50
+ : '';
51
+ return prefix + this.getCommandName();
52
+ }
53
+ getFullOptionsFromPrerequisiteChain() {
54
+ const self = this;
55
+ const uniqueOptions = new Map();
56
+ const visitedCommands = new Set();
57
+ const queue = [self];
58
+ while (queue.length > 0) {
59
+ const cur = queue.shift();
60
+ if (cur) {
61
+ const options = cur.getOptions();
62
+ for (const option of options) {
63
+ const optionName = option.getOptionName();
64
+ if (!uniqueOptions.has(optionName)) {
65
+ uniqueOptions.set(optionName, option);
66
+ }
67
+ }
68
+ visitedCommands.add(cur.getCommandName());
69
+ for (const prereq of cur.getPrerequisites()) {
70
+ if (!visitedCommands.has(prereq.getCommandName())) {
71
+ queue.push(prereq);
72
+ }
73
+ }
74
+ }
75
+ }
76
+ return [...uniqueOptions.values()];
77
+ }
78
+ }
79
+ class BaseCommand extends Command {
80
+ // The following terminal command will initiate with this command
81
+ // `memlab <command-name>`
82
+ getCommandName() {
83
+ const className = this.constructor.name;
84
+ throw new Error(`${className}.getCommandName is not implemented`);
85
+ }
86
+ // get a list of examples
87
+ // examples will be displayed in helper text
88
+ getExamples() {
89
+ return [];
90
+ }
91
+ // get command's category, commands under the same category
92
+ // are grouped together in helper text
93
+ getCategory() {
94
+ return CommandCategory.MISC;
95
+ }
96
+ // The description of this analysis will be printed by
97
+ // `memlab` or `memlab help`
98
+ getDescription() {
99
+ const className = this.constructor.name;
100
+ throw new Error(`${className}.getDescription is not implemented`);
101
+ }
102
+ // get a sequence of commands that must be executed before
103
+ // running this command
104
+ getPrerequisites() {
105
+ return [];
106
+ }
107
+ // internal command will not be listed in helper
108
+ isInternalCommand() {
109
+ return false;
110
+ }
111
+ // get options supported by this command
112
+ getOptions() {
113
+ return [];
114
+ }
115
+ // get subcommands of this command
116
+ // for example command 'A' has two sub-commands 'B' and 'C'
117
+ // CLI supports running in terminal: `memlab A B` or `memlab A C`
118
+ // The parent command will be executed before its subcommands
119
+ getSubCommands() {
120
+ return [];
121
+ }
122
+ // Callback for `memlab <command-name>`
123
+ // Do the memory analysis and print results in this callback
124
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
125
+ run(_options) {
126
+ return __awaiter(this, void 0, void 0, function* () {
127
+ const className = this.constructor.name;
128
+ throw new Error(`${className}.run is not implemented`);
129
+ });
130
+ }
131
+ }
132
+ exports.default = BaseCommand;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { ParsedArgs } from 'minimist';
11
+ import { MemLabConfig, AnyRecord } from '@memlab/core';
12
+ import BaseCommand from './BaseCommand';
13
+ declare type RunCommandOptions = {
14
+ isPrerequisite?: boolean;
15
+ commandIndex?: number;
16
+ configFromOptions: AnyRecord;
17
+ };
18
+ declare class CommandDispatcher {
19
+ private modules;
20
+ private modulePaths;
21
+ private executedCommands;
22
+ private executingCommandStack;
23
+ constructor();
24
+ dispatch(args: ParsedArgs): Promise<void>;
25
+ parseOptions(command: BaseCommand, config: MemLabConfig, args: ParsedArgs): Promise<AnyRecord>;
26
+ private runCommand;
27
+ runSubCommandIfAny(command: BaseCommand, args: ParsedArgs, runCmdOpt: RunCommandOptions): Promise<void>;
28
+ private helper;
29
+ private registerBuiltInCommands;
30
+ private registerCommands;
31
+ private registerCommandsFromDir;
32
+ }
33
+ declare const _default: CommandDispatcher;
34
+ export default _default;
35
+ //# sourceMappingURL=Dispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dispatcher.d.ts","sourceRoot":"","sources":["../src/Dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AACzC,OAAO,EAAC,YAAY,EAAE,SAAS,EAAQ,MAAM,cAAc,CAAC;AAM5D,OAAO,WAAW,MAAM,eAAe,CAAC;AAQxC,aAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,SAAS,CAAC;CAC9B,CAAC;AAYF,cAAM,iBAAiB;IACrB,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,qBAAqB,CAAqB;;IAU5C,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BzC,YAAY,CAChB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,SAAS,CAAC;YAYP,UAAU;IA+ClB,kBAAkB,CACtB,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,iBAAiB,GAC3B,OAAO,CAAC,IAAI,CAAC;YAuBF,MAAM;IAYpB,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,uBAAuB;CA6ChC;;AAED,wBAAuC"}
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ var __importDefault = (this && this.__importDefault) || function (mod) {
21
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ const core_1 = require("@memlab/core");
25
+ const fs_1 = __importDefault(require("fs"));
26
+ const path_1 = __importDefault(require("path"));
27
+ const core_2 = require("@memlab/core");
28
+ const BaseCommand_1 = __importDefault(require("./BaseCommand"));
29
+ const HelperCommand_1 = __importDefault(require("./commands/helper/HelperCommand"));
30
+ const VerboseOption_1 = __importDefault(require("./options/VerboseOption"));
31
+ const SetContinuousTestOption_1 = __importDefault(require("./options/SetContinuousTestOption"));
32
+ const DebugOption_1 = __importDefault(require("./options/DebugOption"));
33
+ const SilentOption_1 = __importDefault(require("./options/SilentOption"));
34
+ const HelperOption_1 = __importDefault(require("./options/HelperOption"));
35
+ const universalOptions = [
36
+ new HelperOption_1.default(),
37
+ new VerboseOption_1.default(),
38
+ new SetContinuousTestOption_1.default(),
39
+ new DebugOption_1.default(),
40
+ new SilentOption_1.default(),
41
+ ];
42
+ const helperCommand = new HelperCommand_1.default();
43
+ helperCommand.setUniversalOptions(universalOptions);
44
+ class CommandDispatcher {
45
+ constructor() {
46
+ this.executedCommands = new Set();
47
+ this.executingCommandStack = [];
48
+ // auto load all command modules
49
+ this.modules = new Map();
50
+ this.modulePaths = new Map();
51
+ this.registerBuiltInCommands();
52
+ this.registerCommands();
53
+ }
54
+ dispatch(args) {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ // triggered by `memlab` (without specific command)
57
+ if (!args._ || !(args._.length >= 1)) {
58
+ core_2.info.error('\n command argument missing');
59
+ yield this.helper(args);
60
+ return;
61
+ }
62
+ const command = args._[0];
63
+ // invalid command, e.g., `memlab xyz`
64
+ if (!this.modules.has(command)) {
65
+ yield this.helper(args);
66
+ return;
67
+ }
68
+ // `memlab <COMMAND> <SUB-COMMAND> -h`
69
+ if (args.h || args.help) {
70
+ yield this.helper(args);
71
+ return;
72
+ }
73
+ // `memlab help <COMMAND> <SUB-COMMAND>`
74
+ if (command === helperCommand.getCommandName()) {
75
+ yield this.helper(Object.assign(Object.assign({}, args), { _: args._.slice(1) }));
76
+ return;
77
+ }
78
+ const module = this.modules.get(command);
79
+ this.executedCommands = new Set();
80
+ this.executingCommandStack = [];
81
+ yield this.runCommand(module, args);
82
+ });
83
+ }
84
+ parseOptions(command, config, args) {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ const options = [...universalOptions, ...command.getOptions()];
87
+ const configFromOptions = Object.create(null);
88
+ for (const option of options) {
89
+ const ret = yield option.run(config, args);
90
+ if (ret) {
91
+ Object.assign(configFromOptions, ret);
92
+ }
93
+ }
94
+ return configFromOptions;
95
+ });
96
+ }
97
+ runCommand(command, args, runCmdOpt = { configFromOptions: {} }) {
98
+ var _a;
99
+ return __awaiter(this, void 0, void 0, function* () {
100
+ const commandName = command.getCommandName();
101
+ // make sure commands on the prerequisite are only executed once
102
+ if (this.executedCommands.has(commandName)) {
103
+ return;
104
+ }
105
+ this.executingCommandStack.push(commandName);
106
+ // execute prerequisites
107
+ const prerequisites = command.getPrerequisites();
108
+ for (const prereq of prerequisites) {
109
+ const prereqName = prereq.getCommandName();
110
+ if (this.executingCommandStack.indexOf(prereqName) > 0) {
111
+ throw new Error(`circular prerequisite reference: ${commandName} <--> ${prereqName}`);
112
+ }
113
+ yield this.runCommand(prereq, args, Object.assign({ isPrerequisite: true }, runCmdOpt));
114
+ }
115
+ // parse command line options
116
+ const c = yield this.parseOptions(command, core_2.config, args);
117
+ Object.assign(runCmdOpt.configFromOptions, c);
118
+ const { configFromOptions } = runCmdOpt;
119
+ // execute command
120
+ yield command.run({ cliArgs: args, configFromOptions });
121
+ if (runCmdOpt.isPrerequisite !== true) {
122
+ // execute subcommands
123
+ const commandIndex = ((_a = runCmdOpt.commandIndex) !== null && _a !== void 0 ? _a : 0) + 1;
124
+ const runSubCmdOpt = Object.assign(Object.assign({}, runCmdOpt), { commandIndex });
125
+ yield this.runSubCommandIfAny(command, args, runSubCmdOpt);
126
+ }
127
+ this.executingCommandStack.pop();
128
+ this.executedCommands.add(commandName);
129
+ });
130
+ }
131
+ runSubCommandIfAny(command, args, runCmdOpt) {
132
+ var _a;
133
+ return __awaiter(this, void 0, void 0, function* () {
134
+ const subCommandIndex = (_a = runCmdOpt.commandIndex) !== null && _a !== void 0 ? _a : 0;
135
+ if (args._.length <= subCommandIndex) {
136
+ return;
137
+ }
138
+ const subCommands = command.getSubCommands();
139
+ for (const subCommand of subCommands) {
140
+ if (subCommand.getCommandName() === args._[subCommandIndex]) {
141
+ this.runCommand(subCommand, args, runCmdOpt);
142
+ return;
143
+ }
144
+ }
145
+ core_2.info.error(`Invalid sub-command \`${args._[subCommandIndex]}\` of \`${command.getCommandName()}\`\n`);
146
+ yield this.helper(args, command);
147
+ });
148
+ }
149
+ helper(cliArgs, command = null) {
150
+ return __awaiter(this, void 0, void 0, function* () {
151
+ yield helperCommand.run({
152
+ modules: this.modules,
153
+ command,
154
+ cliArgs,
155
+ indent: ' ',
156
+ });
157
+ });
158
+ }
159
+ registerBuiltInCommands() {
160
+ // TBA
161
+ }
162
+ registerCommands() {
163
+ const modulesDir = path_1.default.resolve(__dirname, 'commands');
164
+ this.registerCommandsFromDir(modulesDir);
165
+ }
166
+ registerCommandsFromDir(modulesDir) {
167
+ const moduleFiles = fs_1.default.readdirSync(modulesDir);
168
+ for (const moduleFile of moduleFiles) {
169
+ const modulePath = path_1.default.join(modulesDir, moduleFile);
170
+ // recursively import modules from subdirectories
171
+ if (fs_1.default.lstatSync(modulePath).isDirectory()) {
172
+ this.registerCommandsFromDir(modulePath);
173
+ continue;
174
+ }
175
+ // only import modules files ends with with Command.js
176
+ if (!moduleFile.endsWith('Command.js')) {
177
+ continue;
178
+ }
179
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
180
+ const module = require(modulePath);
181
+ const moduleConstructor = typeof module.default === 'function' ? module.default : module;
182
+ const moduleInstance = new moduleConstructor();
183
+ if (!(moduleInstance instanceof BaseCommand_1.default)) {
184
+ core_1.utils.haltOrThrow('loading a command that does not extend BaseCommand');
185
+ }
186
+ const commandName = moduleInstance.getCommandName();
187
+ if (this.modules.has(commandName)) {
188
+ // resolve conflict
189
+ const ossCommandLoaded = !core_2.fileManager.isWithinInternalDirectory(this.modulePaths.get(commandName));
190
+ const loadingOssCommand = !core_2.fileManager.isWithinInternalDirectory(modulePath);
191
+ if (ossCommandLoaded === loadingOssCommand) {
192
+ // when both commands are open source or neither are open source
193
+ core_2.info.midLevel(`MemLab command ${commandName} is already registered`);
194
+ }
195
+ else if (!ossCommandLoaded && loadingOssCommand) {
196
+ // when open source command tries to overwrite non-open source command
197
+ continue;
198
+ }
199
+ }
200
+ this.modules.set(commandName, moduleInstance);
201
+ this.modulePaths.set(commandName, modulePath);
202
+ }
203
+ }
204
+ }
205
+ exports.default = new CommandDispatcher();
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ /// <reference types="node" />
11
+ declare module 'html-inline' {
12
+ interface InlinerParams {
13
+ basedir: string;
14
+ }
15
+ export default function Inliner(params: InlinerParams): NodeJS.ReadWriteStream;
16
+ }
17
+ //# sourceMappingURL=TypesThirdParty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TypesThirdParty.d.ts","sourceRoot":"","sources":["../src/TypesThirdParty.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;;AAEH,OAAO,QAAQ,aAAa,CAAC;IAC3B,UAAU,aAAa;QACrB,OAAO,EAAE,MAAM,CAAC;KACjB;IACD,MAAM,CAAC,OAAO,UAAU,OAAO,CAC7B,MAAM,EAAE,aAAa,GACpB,MAAM,CAAC,eAAe,CAAC;CAC3B"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { CLIOptions } from '@memlab/core';
11
+ import BaseCommand from '../BaseCommand';
12
+ import { BaseOption } from '@memlab/core';
13
+ export default class CleanTraceDataCommand extends BaseCommand {
14
+ getCommandName(): string;
15
+ getDescription(): string;
16
+ isInternalCommand(): boolean;
17
+ getOptions(): BaseOption[];
18
+ run(options: CLIOptions): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=CleanLoggerDataCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CleanLoggerDataCommand.d.ts","sourceRoot":"","sources":["../../src/commands/CleanLoggerDataCommand.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAW,MAAM,cAAc,CAAC;AAEvD,OAAO,WAAW,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAc,UAAU,EAAC,MAAM,cAAc,CAAC;AAIrD,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,WAAW;IAC5D,cAAc,IAAI,MAAM;IAIxB,cAAc,IAAI,MAAM;IAIxB,iBAAiB,IAAI,OAAO;IAI5B,UAAU,IAAI,UAAU,EAAE;IAIpB,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAK9C"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ var __importDefault = (this && this.__importDefault) || function (mod) {
21
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ const BaseCommand_1 = __importDefault(require("../BaseCommand"));
25
+ const core_1 = require("@memlab/core");
26
+ const SetWorkingDirectoryOption_1 = __importDefault(require("../options/SetWorkingDirectoryOption"));
27
+ const InitDirectoryCommand_1 = __importDefault(require("./InitDirectoryCommand"));
28
+ class CleanTraceDataCommand extends BaseCommand_1.default {
29
+ getCommandName() {
30
+ return 'clear-trace-data';
31
+ }
32
+ getDescription() {
33
+ return 'remove all retainer trace data generated from memlab runs';
34
+ }
35
+ isInternalCommand() {
36
+ return true;
37
+ }
38
+ getOptions() {
39
+ return [new SetWorkingDirectoryOption_1.default()];
40
+ }
41
+ run(options) {
42
+ var _a;
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ const workDir = (_a = options.configFromOptions) === null || _a === void 0 ? void 0 : _a.workDir;
45
+ core_1.fileManager.emptyTraceLogDataDir({ workDir });
46
+ yield new InitDirectoryCommand_1.default().run(options);
47
+ });
48
+ }
49
+ }
50
+ exports.default = CleanTraceDataCommand;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { CLIOptions } from '@memlab/core';
11
+ import BaseCommand from '../BaseCommand';
12
+ import { BaseOption } from '@memlab/core';
13
+ export default class CleanRunDataCommand extends BaseCommand {
14
+ getCommandName(): string;
15
+ getDescription(): string;
16
+ isInternalCommand(): boolean;
17
+ getOptions(): BaseOption[];
18
+ run(options: CLIOptions): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=CleanRunDataCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CleanRunDataCommand.d.ts","sourceRoot":"","sources":["../../src/commands/CleanRunDataCommand.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAW,MAAM,cAAc,CAAC;AAEvD,OAAO,WAAW,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAc,UAAU,EAAC,MAAM,cAAc,CAAC;AAGrD,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,WAAW;IAC1D,cAAc,IAAI,MAAM;IAIxB,cAAc,IAAI,MAAM;IAIxB,iBAAiB,IAAI,OAAO;IAI5B,UAAU,IAAI,UAAU,EAAE;IAIpB,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAI9C"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * @emails oncall+ws_labs
9
+ * @format
10
+ */
11
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
12
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
13
+ return new (P || (P = Promise))(function (resolve, reject) {
14
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
17
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
18
+ });
19
+ };
20
+ var __importDefault = (this && this.__importDefault) || function (mod) {
21
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ const BaseCommand_1 = __importDefault(require("../BaseCommand"));
25
+ const core_1 = require("@memlab/core");
26
+ const SetWorkingDirectoryOption_1 = __importDefault(require("../options/SetWorkingDirectoryOption"));
27
+ class CleanRunDataCommand extends BaseCommand_1.default {
28
+ getCommandName() {
29
+ return 'clear-run-data';
30
+ }
31
+ getDescription() {
32
+ return 'remove all web page E2E data generated from memlab runs';
33
+ }
34
+ isInternalCommand() {
35
+ return true;
36
+ }
37
+ getOptions() {
38
+ return [new SetWorkingDirectoryOption_1.default()];
39
+ }
40
+ run(options) {
41
+ var _a;
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ const workDir = (_a = options.configFromOptions) === null || _a === void 0 ? void 0 : _a.workDir;
44
+ core_1.fileManager.clearDataDirs({ workDir });
45
+ });
46
+ }
47
+ }
48
+ exports.default = CleanRunDataCommand;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @emails oncall+ws_labs
8
+ * @format
9
+ */
10
+ import type { CLIOptions } from '@memlab/core';
11
+ import BaseCommand from '../BaseCommand';
12
+ import { BaseOption } from '@memlab/core';
13
+ export default class InitDirectoryCommand extends BaseCommand {
14
+ getCommandName(): string;
15
+ getDescription(): string;
16
+ isInternalCommand(): boolean;
17
+ getOptions(): BaseOption[];
18
+ run(options: CLIOptions): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=InitDirectoryCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InitDirectoryCommand.d.ts","sourceRoot":"","sources":["../../src/commands/InitDirectoryCommand.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,UAAU,EAAW,MAAM,cAAc,CAAC;AAEvD,OAAO,WAAW,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAsB,UAAU,EAAC,MAAM,cAAc,CAAC;AAG7D,MAAM,CAAC,OAAO,OAAO,oBAAqB,SAAQ,WAAW;IAC3D,cAAc,IAAI,MAAM;IAIxB,cAAc,IAAI,MAAM;IAIxB,iBAAiB,IAAI,OAAO;IAI5B,UAAU,IAAI,UAAU,EAAE;IAIpB,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAI9C"}