@tvlabs/wdio-service 0.1.4 → 0.1.6

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.
@@ -0,0 +1,20 @@
1
+ import { Socket, type Channel } from 'phoenix';
2
+ import { Logger } from '../logger.js';
3
+ import type { LogLevel } from '../types.js';
4
+ export declare abstract class BaseChannel {
5
+ protected endpoint: string;
6
+ protected maxReconnectRetries: number;
7
+ protected key: string;
8
+ protected logLevel: LogLevel;
9
+ protected socket: Socket;
10
+ protected log: Logger;
11
+ constructor(endpoint: string, maxReconnectRetries: number, key: string, logLevel: LogLevel | undefined, loggerName: string);
12
+ abstract connect(): Promise<void>;
13
+ abstract disconnect(): Promise<void>;
14
+ protected join(topic: Channel): Promise<void>;
15
+ protected push<T>(topic: Channel, event: string, payload: object): Promise<T>;
16
+ private params;
17
+ private reconnectAfterMs;
18
+ private static logSocketError;
19
+ }
20
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/channels/base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,OAAO,KAAK,EAAsB,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGhE,8BAAsB,WAAW;IAK7B,SAAS,CAAC,QAAQ,EAAE,MAAM;IAC1B,SAAS,CAAC,mBAAmB,EAAE,MAAM;IACrC,SAAS,CAAC,GAAG,EAAE,MAAM;IACrB,SAAS,CAAC,QAAQ,EAAE,QAAQ;IAP9B,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC;gBAGV,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,QAAQ,YAAS,EACrC,UAAU,EAAE,MAAM;IAepB,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACjC,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;cAEpB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;cAgBnC,IAAI,CAAC,CAAC,EACpB,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,CAAC,CAAC;IAgBb,OAAO,CAAC,MAAM;IAWd,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,MAAM,CAAC,cAAc;CAU9B"}
@@ -0,0 +1,16 @@
1
+ import { BaseChannel } from './base.js';
2
+ import type { LogLevel } from '../types.js';
3
+ export declare class BuildChannel extends BaseChannel {
4
+ private lobbyTopic;
5
+ constructor(endpoint: string, maxReconnectRetries: number, key: string, logLevel?: LogLevel);
6
+ disconnect(): Promise<void>;
7
+ connect(): Promise<void>;
8
+ uploadBuild(buildPath: string, appSlug?: string): Promise<string>;
9
+ private requestUploadUrl;
10
+ private uploadToUrl;
11
+ private extractBuildInfo;
12
+ private getFileMetadata;
13
+ private computeSha256;
14
+ private detectMimeType;
15
+ }
16
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/channels/build.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,KAAK,EAIV,QAAQ,EACT,MAAM,aAAa,CAAC;AAErB,qBAAa,YAAa,SAAQ,WAAW;IAC3C,OAAO,CAAC,UAAU,CAAU;gBAG1B,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAAiB;IAYvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAoBzD,gBAAgB;YAgBhB,WAAW;YA8BX,gBAAgB;YAehB,eAAe;YAWf,aAAa;IAW3B,OAAO,CAAC,cAAc;CAYvB"}
@@ -1,13 +1,8 @@
1
- import type { TVLabsCapabilities, LogLevel } from './types.js';
2
- export declare class TVLabsChannel {
3
- private endpoint;
4
- private maxReconnectRetries;
5
- private key;
6
- private logLevel;
7
- private socket;
1
+ import { BaseChannel } from './base.js';
2
+ import type { TVLabsCapabilities, LogLevel } from '../types.js';
3
+ export declare class SessionChannel extends BaseChannel {
8
4
  private lobbyTopic;
9
5
  private requestTopic?;
10
- private log;
11
6
  private readonly events;
12
7
  constructor(endpoint: string, maxReconnectRetries: number, key: string, logLevel?: LogLevel);
13
8
  disconnect(): Promise<void>;
@@ -17,11 +12,6 @@ export declare class TVLabsChannel {
17
12
  private observeRequest;
18
13
  private unobserveRequest;
19
14
  private requestSession;
20
- private join;
21
- private push;
22
- private params;
23
- private reconnectAfterMs;
24
15
  private tvlabsSessionLink;
25
- private static logSocketError;
26
16
  }
27
- //# sourceMappingURL=channel.d.ts.map
17
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/channels/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,KAAK,EACV,kBAAkB,EAGlB,QAAQ,EACT,MAAM,aAAa,CAAC;AAErB,qBAAa,cAAe,SAAQ,WAAW;IAC7C,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAU;IAE/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAOZ;gBAGT,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,QAAiB;IAYvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBxB,UAAU,CACd,YAAY,EAAE,kBAAkB,EAChC,UAAU,EAAE,MAAM,EAClB,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC;YAWJ,WAAW;YAkBX,cAAc;IAsD5B,OAAO,CAAC,gBAAgB;YAUV,cAAc;IAuB5B,OAAO,CAAC,iBAAiB;CAG1B"}
package/esm/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  import { SevereServiceError } from 'webdriverio';
2
- import * as crypto from 'crypto';
2
+ import * as crypto$1 from 'crypto';
3
3
  import { WebSocket } from 'ws';
4
4
  import { Socket } from 'phoenix';
5
+ import * as fs from 'node:fs';
6
+ import * as path from 'node:path';
7
+ import * as crypto from 'node:crypto';
5
8
 
6
9
  const LOG_LEVELS = {
7
10
  error: 0,
@@ -27,9 +30,58 @@ class Logger {
27
30
  formatMessage(level, ...args) {
28
31
  const timestamp = new Date().toISOString();
29
32
  return `${timestamp} ${level.toUpperCase()} ${this.name}: ${args
30
- .map((arg) => typeof arg === 'object' ? JSON.stringify(arg) : String(arg))
33
+ .map((arg) => this.serializeArg(arg))
31
34
  .join(' ')}`;
32
35
  }
36
+ serializeArg(arg) {
37
+ if (typeof arg === 'string' ||
38
+ typeof arg === 'number' ||
39
+ typeof arg === 'boolean') {
40
+ return String(arg);
41
+ }
42
+ if (arg === null || arg === undefined) {
43
+ return String(arg);
44
+ }
45
+ if (arg instanceof Error) {
46
+ return arg.stack || `${arg.name}: ${arg.message}`;
47
+ }
48
+ if (typeof arg === 'object') {
49
+ try {
50
+ const stringified = JSON.stringify(arg, (key, value) => {
51
+ if (value instanceof Error) {
52
+ return `${value.name}: ${value.message}`;
53
+ }
54
+ return value;
55
+ });
56
+ if (stringified === '{}') {
57
+ const keys = Object.getOwnPropertyNames(arg);
58
+ if (keys.length > 0) {
59
+ const props = {};
60
+ keys.forEach((key) => {
61
+ try {
62
+ const value = arg[key];
63
+ if (value instanceof Error) {
64
+ props[key] = `${value.name}: ${value.message}`;
65
+ }
66
+ else {
67
+ props[key] = value;
68
+ }
69
+ }
70
+ catch {
71
+ props[key] = '[unable to access]';
72
+ }
73
+ });
74
+ return JSON.stringify(props);
75
+ }
76
+ }
77
+ return stringified;
78
+ }
79
+ catch {
80
+ return String(arg);
81
+ }
82
+ }
83
+ return String(arg);
84
+ }
33
85
  debug(...args) {
34
86
  if (this.shouldLog('debug')) {
35
87
  console.log(this.formatMessage('debug', ...args));
@@ -58,7 +110,7 @@ class Logger {
58
110
  }
59
111
 
60
112
  var name = "@tvlabs/wdio-service";
61
- var version = "0.1.4";
113
+ var version = "0.1.6";
62
114
  var packageJson = {
63
115
  name: name,
64
116
  version: version};
@@ -76,15 +128,81 @@ function getServiceName() {
76
128
  return packageJson.name;
77
129
  }
78
130
 
79
- class TVLabsChannel {
131
+ class BaseChannel {
80
132
  endpoint;
81
133
  maxReconnectRetries;
82
134
  key;
83
135
  logLevel;
84
136
  socket;
137
+ log;
138
+ constructor(endpoint, maxReconnectRetries, key, logLevel = 'info', loggerName) {
139
+ this.endpoint = endpoint;
140
+ this.maxReconnectRetries = maxReconnectRetries;
141
+ this.key = key;
142
+ this.logLevel = logLevel;
143
+ this.log = new Logger(loggerName, this.logLevel);
144
+ this.socket = new Socket(this.endpoint, {
145
+ transport: WebSocket,
146
+ params: this.params(),
147
+ reconnectAfterMs: this.reconnectAfterMs.bind(this),
148
+ });
149
+ this.socket.onError((...args) => BaseChannel.logSocketError(this.log, ...args));
150
+ }
151
+ async join(topic) {
152
+ return new Promise((res, rej) => {
153
+ topic
154
+ .join()
155
+ .receive('ok', (_resp) => {
156
+ res();
157
+ })
158
+ .receive('error', ({ response }) => {
159
+ rej('Failed to join topic: ' + response);
160
+ })
161
+ .receive('timeout', () => {
162
+ rej('timeout');
163
+ });
164
+ });
165
+ }
166
+ async push(topic, event, payload) {
167
+ return new Promise((res, rej) => {
168
+ topic
169
+ .push(event, payload)
170
+ .receive('ok', (msg) => {
171
+ res(msg);
172
+ })
173
+ .receive('error', (reason) => {
174
+ rej(reason);
175
+ })
176
+ .receive('timeout', () => {
177
+ rej('timeout');
178
+ });
179
+ });
180
+ }
181
+ params() {
182
+ const serviceInfo = getServiceInfo();
183
+ this.log.debug('Info:', serviceInfo);
184
+ return {
185
+ ...serviceInfo,
186
+ api_key: this.key,
187
+ };
188
+ }
189
+ reconnectAfterMs(tries) {
190
+ if (tries > this.maxReconnectRetries) {
191
+ throw new SevereServiceError('Could not connect to TV Labs, please check your connection.');
192
+ }
193
+ const wait = [0, 1000, 3000, 5000][tries] || 10000;
194
+ this.log.info(`[${tries}/${this.maxReconnectRetries}] Waiting ${wait}ms before re-attempting to connect...`);
195
+ return wait;
196
+ }
197
+ static logSocketError(log, event, _transport, _establishedConnections) {
198
+ const error = event.error;
199
+ log.error('Socket error:', error || event);
200
+ }
201
+ }
202
+
203
+ class SessionChannel extends BaseChannel {
85
204
  lobbyTopic;
86
205
  requestTopic;
87
- log;
88
206
  events = {
89
207
  SESSION_READY: 'session:ready',
90
208
  SESSION_FAILED: 'session:failed',
@@ -94,17 +212,7 @@ class TVLabsChannel {
94
212
  REQUEST_MATCHING: 'request:matching',
95
213
  };
96
214
  constructor(endpoint, maxReconnectRetries, key, logLevel = 'info') {
97
- this.endpoint = endpoint;
98
- this.maxReconnectRetries = maxReconnectRetries;
99
- this.key = key;
100
- this.logLevel = logLevel;
101
- this.log = new Logger('@tvlabs/wdio-channel', this.logLevel);
102
- this.socket = new Socket(this.endpoint, {
103
- transport: WebSocket,
104
- params: this.params(),
105
- reconnectAfterMs: this.reconnectAfterMs.bind(this),
106
- });
107
- this.socket.onError((...args) => TVLabsChannel.logSocketError(this.log, ...args));
215
+ super(endpoint, maxReconnectRetries, key, logLevel, '@tvlabs/session-channel');
108
216
  this.lobbyTopic = this.socket.channel('requests:lobby');
109
217
  }
110
218
  async disconnect() {
@@ -116,14 +224,14 @@ class TVLabsChannel {
116
224
  }
117
225
  async connect() {
118
226
  try {
119
- this.log.debug('Connecting to TV Labs...');
227
+ this.log.debug('Connecting to session channel...');
120
228
  this.socket.connect();
121
229
  await this.join(this.lobbyTopic);
122
- this.log.debug('Connected to TV Labs!');
230
+ this.log.debug('Connected to session channel!');
123
231
  }
124
232
  catch (error) {
125
- this.log.error('Error connecting to TV Labs:', error);
126
- throw new SevereServiceError('Could not connect to TV Labs, please check your connection.');
233
+ this.log.error('Error connecting to session channel:', error);
234
+ throw new SevereServiceError('Could not connect to session channel, please check your connection.');
127
235
  }
128
236
  }
129
237
  async newSession(capabilities, maxRetries, retry = 0) {
@@ -201,58 +309,111 @@ class TVLabsChannel {
201
309
  throw error;
202
310
  }
203
311
  }
204
- async join(topic) {
205
- return new Promise((res, rej) => {
206
- topic
207
- .join()
208
- .receive('ok', (_resp) => {
209
- res();
210
- })
211
- .receive('error', ({ response }) => {
212
- rej('Failed to join topic: ' + response);
213
- })
214
- .receive('timeout', () => {
215
- rej('timeout');
216
- });
217
- });
312
+ tvlabsSessionLink(sessionId) {
313
+ return `https://tvlabs.ai/app/sessions/${sessionId}`;
218
314
  }
219
- async push(topic, event, payload) {
220
- return new Promise((res, rej) => {
221
- topic
222
- .push(event, payload)
223
- .receive('ok', (msg) => {
224
- res(msg);
225
- })
226
- .receive('error', (reason) => {
227
- rej(reason);
228
- })
229
- .receive('timeout', () => {
230
- rej('timeout');
231
- });
315
+ }
316
+
317
+ class BuildChannel extends BaseChannel {
318
+ lobbyTopic;
319
+ constructor(endpoint, maxReconnectRetries, key, logLevel = 'info') {
320
+ super(endpoint, maxReconnectRetries, key, logLevel, '@tvlabs/build-channel');
321
+ this.lobbyTopic = this.socket.channel('upload:lobby');
322
+ }
323
+ async disconnect() {
324
+ return new Promise((res, _rej) => {
325
+ this.lobbyTopic.leave();
326
+ this.socket.disconnect(() => res());
232
327
  });
233
328
  }
234
- params() {
235
- const serviceInfo = getServiceInfo();
236
- this.log.debug('Info:', serviceInfo);
237
- return {
238
- ...serviceInfo,
239
- api_key: this.key,
240
- };
329
+ async connect() {
330
+ try {
331
+ this.log.debug('Connecting to build channel...');
332
+ this.socket.connect();
333
+ await this.join(this.lobbyTopic);
334
+ this.log.debug('Connected to build channel!');
335
+ }
336
+ catch (error) {
337
+ this.log.error('Error connecting to build channel:', error);
338
+ throw new SevereServiceError('Could not connect to build channel, please check your connection.');
339
+ }
241
340
  }
242
- reconnectAfterMs(tries) {
243
- if (tries > this.maxReconnectRetries) {
244
- throw new SevereServiceError('Could not connect to TV Labs, please check your connection.');
341
+ async uploadBuild(buildPath, appSlug) {
342
+ const metadata = await this.getFileMetadata(buildPath);
343
+ this.log.info(`Requesting upload for build ${metadata.filename} (${metadata.type}, ${metadata.size} bytes)`);
344
+ const { url, build_id } = await this.requestUploadUrl(metadata, appSlug);
345
+ this.log.info('Uploading build...');
346
+ await this.uploadToUrl(url, buildPath, metadata);
347
+ const { application_id } = await this.extractBuildInfo();
348
+ this.log.info(`Build "${application_id}" processed successfully`);
349
+ return build_id;
350
+ }
351
+ async requestUploadUrl(metadata, appSlug) {
352
+ try {
353
+ return await this.push(this.lobbyTopic, 'request_upload_url', { metadata, application_slug: appSlug });
354
+ }
355
+ catch (error) {
356
+ this.log.error('Error requesting upload URL:', error);
357
+ throw error;
245
358
  }
246
- const wait = [0, 1000, 3000, 5000][tries] || 10000;
247
- this.log.info(`[${tries}/${this.maxReconnectRetries}] Waiting ${wait}ms before re-attempting to connect...`);
248
- return wait;
249
359
  }
250
- tvlabsSessionLink(sessionId) {
251
- return `https://tvlabs.ai/app/sessions/${sessionId}`;
360
+ async uploadToUrl(url, filePath, metadata) {
361
+ try {
362
+ const response = await fetch(url, {
363
+ method: 'PUT',
364
+ headers: {
365
+ 'Content-Type': metadata.type,
366
+ 'Content-Length': String(metadata.size),
367
+ },
368
+ body: fs.createReadStream(filePath),
369
+ duplex: 'half',
370
+ });
371
+ if (!response.ok) {
372
+ throw new SevereServiceError(`Failed to upload build to storage, got ${response.status}`);
373
+ }
374
+ this.log.info('Upload complete');
375
+ }
376
+ catch (error) {
377
+ this.log.error('Error uploading build:', error);
378
+ throw error;
379
+ }
252
380
  }
253
- static logSocketError(log, event, _transport, _establishedConnections) {
254
- const error = event.error;
255
- log.error('Socket error:', error || event);
381
+ async extractBuildInfo() {
382
+ this.log.info('Processing uploaded build...');
383
+ try {
384
+ return await this.push(this.lobbyTopic, 'extract_build_info', {});
385
+ }
386
+ catch (error) {
387
+ this.log.error('Error processing build:', error);
388
+ throw error;
389
+ }
390
+ }
391
+ async getFileMetadata(buildPath) {
392
+ const filename = path.basename(buildPath);
393
+ const size = fs.statSync(buildPath).size;
394
+ const type = this.detectMimeType(filename);
395
+ const sha256 = await this.computeSha256(buildPath);
396
+ return { filename, type, size, sha256 };
397
+ }
398
+ async computeSha256(buildPath) {
399
+ return new Promise((resolve, reject) => {
400
+ const hash = crypto.createHash('sha256');
401
+ const stream = fs.createReadStream(buildPath);
402
+ stream.on('data', (chunk) => hash.update(chunk));
403
+ stream.on('end', () => resolve(hash.digest('hex')));
404
+ stream.on('error', (err) => reject(err));
405
+ });
406
+ }
407
+ detectMimeType(filename) {
408
+ const fileExtension = path.extname(filename).toLowerCase();
409
+ switch (fileExtension) {
410
+ case '.apk':
411
+ return 'application/vnd.android.package-archive';
412
+ case '.zip':
413
+ return 'application/zip';
414
+ default:
415
+ return 'application/octet-stream';
416
+ }
256
417
  }
257
418
  }
258
419
 
@@ -276,15 +437,22 @@ class TVLabsService {
276
437
  }
277
438
  }
278
439
  async beforeSession(_config, capabilities, _specs, _cid) {
279
- const channel = new TVLabsChannel(this.endpoint(), this.reconnectRetries(), this.apiKey(), this.logLevel());
280
- await channel.connect();
281
- capabilities['tvlabs:session_id'] = await channel.newSession(capabilities, this.retries());
282
- await channel.disconnect();
440
+ const buildPath = this.buildPath();
441
+ if (buildPath) {
442
+ const buildChannel = new BuildChannel(this.buildEndpoint(), this.reconnectRetries(), this.apiKey(), this.logLevel());
443
+ await buildChannel.connect();
444
+ capabilities['tvlabs:build'] = await buildChannel.uploadBuild(buildPath, this.appSlug());
445
+ await buildChannel.disconnect();
446
+ }
447
+ const sessionChannel = new SessionChannel(this.sessionEndpoint(), this.reconnectRetries(), this.apiKey(), this.logLevel());
448
+ await sessionChannel.connect();
449
+ capabilities['tvlabs:session_id'] = await sessionChannel.newSession(capabilities, this.retries());
450
+ await sessionChannel.disconnect();
283
451
  }
284
452
  setupRequestId() {
285
453
  const originalTransformRequest = this._config.transformRequest;
286
454
  this._config.transformRequest = (requestOptions) => {
287
- const requestId = crypto.randomUUID();
455
+ const requestId = crypto$1.randomUUID();
288
456
  const originalRequestOptions = typeof originalTransformRequest === 'function'
289
457
  ? originalTransformRequest(requestOptions)
290
458
  : requestOptions;
@@ -309,8 +477,17 @@ class TVLabsService {
309
477
  }
310
478
  }
311
479
  }
312
- endpoint() {
313
- return this._options.endpoint ?? 'wss://tvlabs.ai/appium';
480
+ buildPath() {
481
+ return this._options.buildPath;
482
+ }
483
+ appSlug() {
484
+ return this._options.app;
485
+ }
486
+ sessionEndpoint() {
487
+ return this._options.sessionEndpoint ?? 'wss://tvlabs.ai/appium';
488
+ }
489
+ buildEndpoint() {
490
+ return this._options.buildEndpoint ?? 'wss://tvlabs.ai/cli';
314
491
  }
315
492
  retries() {
316
493
  return this._options.retries ?? 3;
package/esm/logger.d.ts CHANGED
@@ -5,6 +5,7 @@ export declare class Logger {
5
5
  constructor(name: string, logLevel?: LogLevel);
6
6
  private shouldLog;
7
7
  private formatMessage;
8
+ private serializeArg;
8
9
  debug(...args: unknown[]): void;
9
10
  info(...args: unknown[]): void;
10
11
  warn(...args: unknown[]): void;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc3C,qBAAa,MAAM;IAEf,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;gBADR,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAiB;IAGrC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,aAAa;IASrB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAKhC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAc3C,qBAAa,MAAM;IAEf,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,QAAQ;gBADR,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,QAAiB;IAGrC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,YAAY;IA2DpB,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAM/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAKhC"}
package/esm/service.d.ts CHANGED
@@ -10,7 +10,10 @@ export default class TVLabsService implements Services.ServiceInstance {
10
10
  beforeSession(_config: Omit<Options.Testrunner, 'capabilities'>, capabilities: TVLabsCapabilities, _specs: string[], _cid: string): Promise<void>;
11
11
  private setupRequestId;
12
12
  private setRequestHeader;
13
- private endpoint;
13
+ private buildPath;
14
+ private appSlug;
15
+ private sessionEndpoint;
16
+ private buildEndpoint;
14
17
  private retries;
15
18
  private apiKey;
16
19
  private logLevel;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,OAAO,OAAO,aAAc,YAAW,QAAQ,CAAC,eAAe;IAIlE,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,OAAO;IALjB,OAAO,CAAC,GAAG,CAAS;gBAGV,QAAQ,EAAE,oBAAoB,EAC9B,aAAa,EAAE,YAAY,CAAC,8BAA8B,EAC1D,OAAO,EAAE,OAAO,CAAC,WAAW;IAQtC,SAAS,CACP,OAAO,EAAE,OAAO,CAAC,UAAU,EAC3B,KAAK,EAAE,YAAY,CAAC,sBAAsB;IAStC,aAAa,CACjB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,EACjD,YAAY,EAAE,kBAAkB,EAChC,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,MAAM;IAmBd,OAAO,CAAC,cAAc;IA0BtB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;CAGzB"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,OAAO,OAAO,aAAc,YAAW,QAAQ,CAAC,eAAe;IAIlE,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,OAAO;IALjB,OAAO,CAAC,GAAG,CAAS;gBAGV,QAAQ,EAAE,oBAAoB,EAC9B,aAAa,EAAE,YAAY,CAAC,8BAA8B,EAC1D,OAAO,EAAE,OAAO,CAAC,WAAW;IAQtC,SAAS,CACP,OAAO,EAAE,OAAO,CAAC,UAAU,EAC3B,KAAK,EAAE,YAAY,CAAC,sBAAsB;IAStC,aAAa,CACjB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,cAAc,CAAC,EACjD,YAAY,EAAE,kBAAkB,EAChC,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,MAAM;IAuCd,OAAO,CAAC,cAAc;IA0BtB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;CAGzB"}
package/esm/types.d.ts CHANGED
@@ -2,8 +2,11 @@ import type { Capabilities } from '@wdio/types';
2
2
  export type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
3
3
  export type TVLabsServiceOptions = {
4
4
  apiKey: string;
5
- endpoint?: string;
5
+ sessionEndpoint?: string;
6
+ buildEndpoint?: string;
6
7
  retries?: number;
8
+ buildPath?: string;
9
+ app?: string;
7
10
  reconnectRetries?: number;
8
11
  attachRequestId?: boolean;
9
12
  };
@@ -38,4 +41,17 @@ export type TVLabsServiceInfo = {
38
41
  service_version: string;
39
42
  service_name: string;
40
43
  };
44
+ export type TVLabsRequestUploadUrlResponse = {
45
+ url: string;
46
+ build_id: string;
47
+ };
48
+ export type TVLabsExtractBuildInfoResponse = {
49
+ application_id: string;
50
+ };
51
+ export type TVLabsBuildMetadata = {
52
+ filename: string;
53
+ type: string;
54
+ size: number;
55
+ sha256: string;
56
+ };
41
57
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEhF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC5B,YAAY,CAAC,+BAA+B,GAAG;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,kCAAkC,CAAC,EAAE,MAAM,CAAC;QAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC,CAAC;IACF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEJ,MAAM,MAAM,gCAAgC,GAAG,CAC7C,QAAQ,EAAE,0BAA0B,KACjC,IAAI,CAAC;AAEV,MAAM,MAAM,0BAA0B,GAAG;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,GAAG;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEhF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC5B,YAAY,CAAC,+BAA+B,GAAG;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,kCAAkC,CAAC,EAAE,MAAM,CAAC;QAC5C,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC,CAAC;IACF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEJ,MAAM,MAAM,gCAAgC,GAAG,CAC7C,QAAQ,EAAE,0BAA0B,KACjC,IAAI,CAAC;AAEV,MAAM,MAAM,0BAA0B,GAAG;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,GAAG;IACnD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG;IAC3C,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tvlabs/wdio-service",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "WebdriverIO service that provides a better integration into TV Labs",
5
5
  "author": "Regan Karlewicz <regan@tvlabs.ai>",
6
6
  "license": "Apache-2.0",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "git+https://github.com/tv-labs/wdio-tvlabs-service.git"
12
+ "url": "git+https://github.com/tv-labs/wdio-service.git"
13
13
  },
14
14
  "keywords": [
15
15
  "wdio-plugin",
@@ -19,7 +19,7 @@
19
19
  "appium"
20
20
  ],
21
21
  "bugs": {
22
- "url": "https://github.com/tv-labs/wdio-tvlabs-service/issues"
22
+ "url": "https://github.com/tv-labs/wdio-service/issues"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "npm run clean && rollup -c",
@@ -29,7 +29,8 @@
29
29
  "format": "prettier --write .",
30
30
  "format:check": "prettier --check .",
31
31
  "lint": "eslint",
32
- "test": "vitest --config vitest.config.ts --coverage",
32
+ "test": "vitest --config vitest.config.ts --coverage --run",
33
+ "test:watch": "vitest --config vitest.config.ts --coverage",
33
34
  "publish:dry": "npm publish --access public --provenance --dry-run"
34
35
  },
35
36
  "type": "module",
@@ -46,11 +47,11 @@
46
47
  "@rollup/plugin-json": "^6.1.0",
47
48
  "@rollup/plugin-node-resolve": "^16.0.1",
48
49
  "@rollup/plugin-typescript": "^12.1.4",
49
- "@types/node": "^22.13.10",
50
+ "@types/node": "^24.1.0",
50
51
  "@types/phoenix": "^1.6.6",
51
52
  "@types/ws": "^8.18.0",
52
- "@typescript-eslint/eslint-plugin": "^8.36.0",
53
- "@typescript-eslint/parser": "^8.36.0",
53
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
54
+ "@typescript-eslint/parser": "^8.38.0",
54
55
  "@vitest/coverage-v8": "^3.0.9",
55
56
  "@wdio/globals": "^9.12.1",
56
57
  "@wdio/types": "^9.10.1",
@@ -60,7 +61,7 @@
60
61
  "prettier": "^3.5.3",
61
62
  "rollup": "^4.45.1",
62
63
  "typescript": "^5.8.2",
63
- "typescript-eslint": "^8.36.0",
64
+ "typescript-eslint": "^8.38.0",
64
65
  "vitest": "^3.0.9",
65
66
  "webdriverio": "^9.12.1"
66
67
  },