@testingbot/cli 1.0.1 → 1.0.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 (42) hide show
  1. package/README.md +3 -2
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +55 -8
  4. package/dist/models/espresso_options.d.ts +9 -0
  5. package/dist/models/espresso_options.d.ts.map +1 -1
  6. package/dist/models/espresso_options.js +14 -0
  7. package/dist/models/maestro_options.d.ts +19 -7
  8. package/dist/models/maestro_options.d.ts.map +1 -1
  9. package/dist/models/maestro_options.js +17 -8
  10. package/dist/models/testingbot_error.d.ts +3 -0
  11. package/dist/models/testingbot_error.d.ts.map +1 -1
  12. package/dist/models/testingbot_error.js +5 -0
  13. package/dist/models/xcuitest_options.d.ts +9 -0
  14. package/dist/models/xcuitest_options.d.ts.map +1 -1
  15. package/dist/models/xcuitest_options.js +14 -0
  16. package/dist/providers/base_provider.d.ts +119 -0
  17. package/dist/providers/base_provider.d.ts.map +1 -0
  18. package/dist/providers/base_provider.js +296 -0
  19. package/dist/providers/espresso.d.ts +14 -21
  20. package/dist/providers/espresso.d.ts.map +1 -1
  21. package/dist/providers/espresso.js +39 -168
  22. package/dist/providers/login.d.ts +1 -0
  23. package/dist/providers/login.d.ts.map +1 -1
  24. package/dist/providers/login.js +16 -7
  25. package/dist/providers/maestro.d.ts +53 -21
  26. package/dist/providers/maestro.d.ts.map +1 -1
  27. package/dist/providers/maestro.js +614 -263
  28. package/dist/providers/xcuitest.d.ts +14 -21
  29. package/dist/providers/xcuitest.d.ts.map +1 -1
  30. package/dist/providers/xcuitest.js +39 -168
  31. package/dist/upload.d.ts +10 -0
  32. package/dist/upload.d.ts.map +1 -1
  33. package/dist/upload.js +46 -21
  34. package/dist/utils/connectivity.d.ts +25 -0
  35. package/dist/utils/connectivity.d.ts.map +1 -0
  36. package/dist/utils/connectivity.js +118 -0
  37. package/dist/utils/error-helpers.d.ts +26 -0
  38. package/dist/utils/error-helpers.d.ts.map +1 -0
  39. package/dist/utils/error-helpers.js +237 -0
  40. package/dist/utils.d.ts.map +1 -1
  41. package/dist/utils.js +7 -2
  42. package/package.json +1 -1
@@ -0,0 +1,119 @@
1
+ import Credentials from '../models/credentials';
2
+ import TestingBotError from '../models/testingbot_error';
3
+ import Upload from '../upload';
4
+ /**
5
+ * Common interface for run information shared by all providers
6
+ */
7
+ export interface BaseRunInfo {
8
+ id: number;
9
+ status: 'WAITING' | 'READY' | 'DONE' | 'FAILED';
10
+ capabilities: {
11
+ deviceName: string;
12
+ platformName: string;
13
+ version?: string;
14
+ };
15
+ success: number;
16
+ report?: string;
17
+ }
18
+ /**
19
+ * Common interface for provider options
20
+ */
21
+ export interface BaseProviderOptions {
22
+ quiet?: boolean;
23
+ reportOutputDir?: string;
24
+ }
25
+ /**
26
+ * Abstract base class for test providers (Espresso, XCUITest, Maestro)
27
+ * Contains common functionality shared across all providers.
28
+ */
29
+ export default abstract class BaseProvider<TOptions extends BaseProviderOptions> {
30
+ protected readonly POLL_INTERVAL_MS = 5000;
31
+ protected readonly MAX_POLL_ATTEMPTS = 720;
32
+ protected credentials: Credentials;
33
+ protected options: TOptions;
34
+ protected upload: Upload;
35
+ protected appId: number | undefined;
36
+ protected activeRunIds: number[];
37
+ protected isShuttingDown: boolean;
38
+ protected signalHandler: (() => void) | null;
39
+ /**
40
+ * The base URL for the provider's API endpoint
41
+ */
42
+ protected abstract readonly URL: string;
43
+ constructor(credentials: Credentials, options: TOptions);
44
+ /**
45
+ * Ensures an output directory exists, creating it if necessary.
46
+ */
47
+ protected ensureOutputDirectory(dirPath: string): Promise<void>;
48
+ /**
49
+ * Sets up signal handlers for graceful shutdown (SIGINT, SIGTERM)
50
+ */
51
+ protected setupSignalHandlers(): void;
52
+ /**
53
+ * Removes signal handlers
54
+ */
55
+ protected removeSignalHandlers(): void;
56
+ /**
57
+ * Handles graceful shutdown when interrupt signal is received
58
+ */
59
+ protected handleShutdown(): void;
60
+ /**
61
+ * Stops all active test runs
62
+ */
63
+ protected stopActiveRuns(): Promise<void>;
64
+ /**
65
+ * Stops a specific test run
66
+ */
67
+ protected stopRun(runId: number): Promise<void>;
68
+ /**
69
+ * Clears the current line in the terminal
70
+ */
71
+ protected clearLine(): void;
72
+ /**
73
+ * Sleeps for the specified number of milliseconds
74
+ */
75
+ protected sleep(ms: number): Promise<void>;
76
+ /**
77
+ * Maximum number of retries for transient errors
78
+ */
79
+ protected readonly MAX_RETRIES = 3;
80
+ /**
81
+ * Base delay for exponential backoff (in milliseconds)
82
+ */
83
+ protected readonly BASE_RETRY_DELAY_MS = 2000;
84
+ /**
85
+ * Executes an async operation with automatic retry for transient errors.
86
+ * Uses exponential backoff between retries.
87
+ *
88
+ * @param operation - Description of the operation (for logging)
89
+ * @param fn - Async function to execute
90
+ * @returns The result of the function
91
+ * @throws The last error if all retries fail
92
+ */
93
+ protected withRetry<T>(operation: string, fn: () => Promise<T>): Promise<T>;
94
+ /**
95
+ * Extracts an error message from various error types.
96
+ * For Axios errors, uses enhanced error handling with diagnostics.
97
+ */
98
+ protected extractErrorMessage(cause: unknown): string | null;
99
+ /**
100
+ * Checks internet connectivity and logs diagnostic information.
101
+ * Useful when network errors occur to help users troubleshoot.
102
+ */
103
+ protected checkAndReportConnectivity(): Promise<boolean>;
104
+ /**
105
+ * Performs a quick connectivity check before starting operations.
106
+ * Throws an error with diagnostics if no connection is available.
107
+ */
108
+ protected ensureConnectivity(): Promise<void>;
109
+ /**
110
+ * Handles errors with enhanced diagnostics.
111
+ * For network errors, performs connectivity check.
112
+ */
113
+ protected handleErrorWithDiagnostics(error: unknown, operation: string): Promise<TestingBotError>;
114
+ /**
115
+ * Formats elapsed time in human-readable format
116
+ */
117
+ protected formatElapsedTime(seconds: number): string;
118
+ }
119
+ //# sourceMappingURL=base_provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base_provider.d.ts","sourceRoot":"","sources":["../../src/providers/base_provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,296 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const axios_1 = __importDefault(require("axios"));
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const testingbot_error_1 = __importDefault(require("../models/testingbot_error"));
9
+ const utils_1 = __importDefault(require("../utils"));
10
+ const upload_1 = __importDefault(require("../upload"));
11
+ const platform_1 = __importDefault(require("../utils/platform"));
12
+ const logger_1 = __importDefault(require("../logger"));
13
+ const error_helpers_1 = require("../utils/error-helpers");
14
+ const connectivity_1 = require("../utils/connectivity");
15
+ /**
16
+ * Abstract base class for test providers (Espresso, XCUITest, Maestro)
17
+ * Contains common functionality shared across all providers.
18
+ */
19
+ class BaseProvider {
20
+ POLL_INTERVAL_MS = 5000;
21
+ MAX_POLL_ATTEMPTS = 720; // 1 hour max with 5s interval
22
+ credentials;
23
+ options;
24
+ upload;
25
+ appId = undefined;
26
+ activeRunIds = [];
27
+ isShuttingDown = false;
28
+ signalHandler = null;
29
+ constructor(credentials, options) {
30
+ this.credentials = credentials;
31
+ this.options = options;
32
+ this.upload = new upload_1.default();
33
+ }
34
+ /**
35
+ * Ensures an output directory exists, creating it if necessary.
36
+ */
37
+ async ensureOutputDirectory(dirPath) {
38
+ try {
39
+ const stat = await node_fs_1.default.promises.stat(dirPath);
40
+ if (!stat.isDirectory()) {
41
+ throw new testingbot_error_1.default(`Report output path exists but is not a directory: ${dirPath}`);
42
+ }
43
+ }
44
+ catch (error) {
45
+ if (error instanceof Error &&
46
+ 'code' in error &&
47
+ error.code === 'ENOENT') {
48
+ try {
49
+ await node_fs_1.default.promises.mkdir(dirPath, { recursive: true });
50
+ }
51
+ catch (mkdirError) {
52
+ throw new testingbot_error_1.default(`Failed to create report output directory: ${dirPath}`, { cause: mkdirError });
53
+ }
54
+ }
55
+ else if (error instanceof testingbot_error_1.default) {
56
+ throw error;
57
+ }
58
+ else {
59
+ throw new testingbot_error_1.default(`Failed to access report output directory: ${dirPath}`, { cause: error });
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * Sets up signal handlers for graceful shutdown (SIGINT, SIGTERM)
65
+ */
66
+ setupSignalHandlers() {
67
+ this.signalHandler = () => {
68
+ this.handleShutdown();
69
+ };
70
+ platform_1.default.setupSignalHandlers(this.signalHandler);
71
+ }
72
+ /**
73
+ * Removes signal handlers
74
+ */
75
+ removeSignalHandlers() {
76
+ if (this.signalHandler) {
77
+ platform_1.default.removeSignalHandlers(this.signalHandler);
78
+ this.signalHandler = null;
79
+ }
80
+ }
81
+ /**
82
+ * Handles graceful shutdown when interrupt signal is received
83
+ */
84
+ handleShutdown() {
85
+ if (this.isShuttingDown) {
86
+ logger_1.default.warn('Force exiting...');
87
+ process.exit(1);
88
+ }
89
+ this.isShuttingDown = true;
90
+ this.clearLine();
91
+ logger_1.default.info('Received interrupt signal, stopping test runs...');
92
+ this.stopActiveRuns()
93
+ .then(() => {
94
+ logger_1.default.info('All test runs have been stopped.');
95
+ process.exit(1);
96
+ })
97
+ .catch((error) => {
98
+ logger_1.default.error(`Failed to stop some test runs: ${error instanceof Error ? error.message : error}`);
99
+ process.exit(1);
100
+ });
101
+ }
102
+ /**
103
+ * Stops all active test runs
104
+ */
105
+ async stopActiveRuns() {
106
+ if (!this.appId || this.activeRunIds.length === 0) {
107
+ return;
108
+ }
109
+ const stopPromises = this.activeRunIds.map((runId) => this.stopRun(runId).catch((error) => {
110
+ logger_1.default.error(`Failed to stop run ${runId}: ${error instanceof Error ? error.message : error}`);
111
+ }));
112
+ await Promise.all(stopPromises);
113
+ }
114
+ /**
115
+ * Stops a specific test run
116
+ */
117
+ async stopRun(runId) {
118
+ if (!this.appId) {
119
+ return;
120
+ }
121
+ try {
122
+ await axios_1.default.post(`${this.URL}/${this.appId}/${runId}/stop`, {}, {
123
+ headers: {
124
+ 'User-Agent': utils_1.default.getUserAgent(),
125
+ },
126
+ auth: {
127
+ username: this.credentials.userName,
128
+ password: this.credentials.accessKey,
129
+ },
130
+ });
131
+ if (!this.options.quiet) {
132
+ logger_1.default.info(`Stopped run ${runId}`);
133
+ }
134
+ }
135
+ catch {
136
+ // Ignore errors when stopping runs (may already be stopped)
137
+ }
138
+ }
139
+ /**
140
+ * Clears the current line in the terminal
141
+ */
142
+ clearLine() {
143
+ platform_1.default.clearLine();
144
+ }
145
+ /**
146
+ * Sleeps for the specified number of milliseconds
147
+ */
148
+ sleep(ms) {
149
+ return new Promise((resolve) => setTimeout(resolve, ms));
150
+ }
151
+ /**
152
+ * Maximum number of retries for transient errors
153
+ */
154
+ MAX_RETRIES = 3;
155
+ /**
156
+ * Base delay for exponential backoff (in milliseconds)
157
+ */
158
+ BASE_RETRY_DELAY_MS = 2000;
159
+ /**
160
+ * Executes an async operation with automatic retry for transient errors.
161
+ * Uses exponential backoff between retries.
162
+ *
163
+ * @param operation - Description of the operation (for logging)
164
+ * @param fn - Async function to execute
165
+ * @returns The result of the function
166
+ * @throws The last error if all retries fail
167
+ */
168
+ async withRetry(operation, fn) {
169
+ let lastError;
170
+ for (let attempt = 0; attempt <= this.MAX_RETRIES; attempt++) {
171
+ try {
172
+ return await fn();
173
+ }
174
+ catch (error) {
175
+ lastError = error;
176
+ // Check if this is a retryable error
177
+ const isRetryable = axios_1.default.isAxiosError(error) && (0, error_helpers_1.isRetryableError)(error);
178
+ // Don't retry non-retryable errors or on the last attempt
179
+ if (!isRetryable || attempt === this.MAX_RETRIES) {
180
+ break;
181
+ }
182
+ // Calculate delay with exponential backoff: 2s, 4s, 8s
183
+ const delay = this.BASE_RETRY_DELAY_MS * Math.pow(2, attempt);
184
+ if (!this.options.quiet) {
185
+ const statusCode = axios_1.default.isAxiosError(error)
186
+ ? error.response?.status
187
+ : undefined;
188
+ logger_1.default.warn(`${operation} failed${statusCode ? ` (HTTP ${statusCode})` : ''}, retrying in ${delay / 1000}s... (attempt ${attempt + 1}/${this.MAX_RETRIES})`);
189
+ }
190
+ await this.sleep(delay);
191
+ }
192
+ }
193
+ // All retries failed, throw the error
194
+ throw lastError;
195
+ }
196
+ /**
197
+ * Extracts an error message from various error types.
198
+ * For Axios errors, uses enhanced error handling with diagnostics.
199
+ */
200
+ extractErrorMessage(cause) {
201
+ if (typeof cause === 'string') {
202
+ return cause;
203
+ }
204
+ if (Array.isArray(cause)) {
205
+ return cause.join('\n');
206
+ }
207
+ if (cause && typeof cause === 'object') {
208
+ // Use enhanced error handling for real Axios errors
209
+ if (axios_1.default.isAxiosError(cause)) {
210
+ const enhanced = (0, error_helpers_1.handleAxiosError)(cause, 'Request failed');
211
+ return enhanced.message;
212
+ }
213
+ // Handle error-like objects with response property (for backwards compatibility)
214
+ const axiosLikeError = cause;
215
+ // Check for 429 status code (credits depleted)
216
+ if (axiosLikeError.response?.status === 429) {
217
+ return 'Your TestingBot credits are depleted. Please upgrade your plan at https://testingbot.com/pricing';
218
+ }
219
+ // Extract error message from response data
220
+ if (axiosLikeError.response?.data?.errors) {
221
+ return axiosLikeError.response.data.errors.join('\n');
222
+ }
223
+ if (axiosLikeError.response?.data?.error) {
224
+ return axiosLikeError.response.data.error;
225
+ }
226
+ if (axiosLikeError.response?.data?.message) {
227
+ return axiosLikeError.response.data.message;
228
+ }
229
+ if (cause instanceof Error) {
230
+ return cause.message;
231
+ }
232
+ const obj = cause;
233
+ if (obj.errors) {
234
+ return obj.errors.join('\n');
235
+ }
236
+ if (obj.error) {
237
+ return obj.error;
238
+ }
239
+ if (obj.message) {
240
+ return obj.message;
241
+ }
242
+ }
243
+ return null;
244
+ }
245
+ /**
246
+ * Checks internet connectivity and logs diagnostic information.
247
+ * Useful when network errors occur to help users troubleshoot.
248
+ */
249
+ async checkAndReportConnectivity() {
250
+ logger_1.default.info('Checking internet connectivity...');
251
+ const result = await (0, connectivity_1.checkInternetConnectivity)();
252
+ logger_1.default.info((0, connectivity_1.formatConnectivityResults)(result));
253
+ return result.connected;
254
+ }
255
+ /**
256
+ * Performs a quick connectivity check before starting operations.
257
+ * Throws an error with diagnostics if no connection is available.
258
+ */
259
+ async ensureConnectivity() {
260
+ const result = await (0, connectivity_1.checkInternetConnectivity)();
261
+ if (!result.connected) {
262
+ logger_1.default.error('No internet connection detected.');
263
+ logger_1.default.error((0, connectivity_1.formatConnectivityResults)(result));
264
+ throw new testingbot_error_1.default('No internet connection. Please check your network and try again.');
265
+ }
266
+ }
267
+ /**
268
+ * Handles errors with enhanced diagnostics.
269
+ * For network errors, performs connectivity check.
270
+ */
271
+ async handleErrorWithDiagnostics(error, operation) {
272
+ if (axios_1.default.isAxiosError(error)) {
273
+ // For network errors, check connectivity
274
+ if ((0, error_helpers_1.isNetworkError)(error)) {
275
+ await this.checkAndReportConnectivity();
276
+ }
277
+ return (0, error_helpers_1.handleAxiosError)(error, operation);
278
+ }
279
+ if (error instanceof testingbot_error_1.default) {
280
+ return error;
281
+ }
282
+ return new testingbot_error_1.default(`${operation}: ${error instanceof Error ? error.message : 'Unknown error'}`, { cause: error instanceof Error ? error : undefined });
283
+ }
284
+ /**
285
+ * Formats elapsed time in human-readable format
286
+ */
287
+ formatElapsedTime(seconds) {
288
+ if (seconds < 60) {
289
+ return `${seconds}s`;
290
+ }
291
+ const minutes = Math.floor(seconds / 60);
292
+ const remainingSeconds = seconds % 60;
293
+ return `${minutes}m ${remainingSeconds}s`;
294
+ }
295
+ }
296
+ exports.default = BaseProvider;
@@ -1,5 +1,11 @@
1
1
  import EspressoOptions from '../models/espresso_options';
2
2
  import Credentials from '../models/credentials';
3
+ import BaseProvider from './base_provider';
4
+ export interface EspressoRunEnvironment {
5
+ device?: string;
6
+ name?: string;
7
+ version?: string;
8
+ }
3
9
  export interface EspressoRunInfo {
4
10
  id: number;
5
11
  status: 'WAITING' | 'READY' | 'DONE' | 'FAILED';
@@ -8,6 +14,7 @@ export interface EspressoRunInfo {
8
14
  platformName: string;
9
15
  version?: string;
10
16
  };
17
+ environment?: EspressoRunEnvironment;
11
18
  success: number;
12
19
  report?: string;
13
20
  }
@@ -24,23 +31,13 @@ export interface EspressoSocketMessage {
24
31
  id: number;
25
32
  payload: string;
26
33
  }
27
- export default class Espresso {
28
- private readonly URL;
29
- private readonly POLL_INTERVAL_MS;
30
- private readonly MAX_POLL_ATTEMPTS;
31
- private credentials;
32
- private options;
33
- private upload;
34
- private appId;
35
- private activeRunIds;
36
- private isShuttingDown;
37
- private signalHandler;
34
+ export default class Espresso extends BaseProvider<EspressoOptions> {
35
+ protected readonly URL = "https://api.testingbot.com/v1/app-automate/espresso";
38
36
  private socket;
39
37
  private updateServer;
40
38
  private updateKey;
41
39
  constructor(credentials: Credentials, options: EspressoOptions);
42
40
  private validate;
43
- private ensureOutputDirectory;
44
41
  run(): Promise<EspressoResult>;
45
42
  private uploadApp;
46
43
  private uploadTestApp;
@@ -48,17 +45,13 @@ export default class Espresso {
48
45
  private getStatus;
49
46
  private waitForCompletion;
50
47
  private displayRunStatus;
51
- private clearLine;
52
- private formatElapsedTime;
48
+ /**
49
+ * Get the display name for a run, preferring environment.name over capabilities.deviceName
50
+ * This shows the actual device used when a wildcard (*) was specified
51
+ */
52
+ private getRunDisplayName;
53
53
  private getStatusInfo;
54
54
  private fetchReports;
55
- private sleep;
56
- private extractErrorMessage;
57
- private setupSignalHandlers;
58
- private removeSignalHandlers;
59
- private handleShutdown;
60
- private stopActiveRuns;
61
- private stopRun;
62
55
  private connectToUpdateServer;
63
56
  private disconnectFromUpdateServer;
64
57
  private handleEspressoData;
@@ -1 +1 @@
1
- {"version":3,"file":"espresso.d.ts","sourceRoot":"","sources":["../../src/providers/espresso.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,4BAA4B,CAAC;AAEzD,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAUhD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,YAAY,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,eAAe,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAyD;IAC7E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAO;IAEzC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,SAAS,CAAuB;gBAErB,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe;YAMvD,QAAQ;YAuCR,qBAAqB;IA6BtB,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC;YA4D7B,SAAS;YAaT,aAAa;YAYb,QAAQ;YAsDR,SAAS;YAoBT,iBAAiB;IAwE/B,OAAO,CAAC,gBAAgB;IAmCxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,aAAa;YAkBP,YAAY;IAmD1B,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,mBAAmB;IAiD3B,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,cAAc;YAuBR,cAAc;YAgBd,OAAO;IA8BrB,OAAO,CAAC,qBAAqB;IAqC7B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,mBAAmB;CAa5B"}
1
+ {"version":3,"file":"espresso.d.ts","sourceRoot":"","sources":["../../src/providers/espresso.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,4BAA4B,CAAC;AAEzD,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAOhD,OAAO,YAAY,MAAM,iBAAiB,CAAC;AAE3C,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,YAAY,EAAE;QACZ,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,eAAe,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,CAAC,OAAO,OAAO,QAAS,SAAQ,YAAY,CAAC,eAAe,CAAC;IACjE,SAAS,CAAC,QAAQ,CAAC,GAAG,yDACkC;IAExD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,SAAS,CAAuB;gBAErB,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe;YAIvD,QAAQ;IAuCT,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC;YA+D7B,SAAS;YAaT,aAAa;YAYb,QAAQ;YA0DR,SAAS;YA4BT,iBAAiB;IAwE/B,OAAO,CAAC,gBAAgB;IAmCxB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,aAAa;YAkBP,YAAY;IAwD1B,OAAO,CAAC,qBAAqB;IAqC7B,OAAO,CAAC,0BAA0B;IAOlC,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,mBAAmB;CAa5B"}