@percy/client 1.32.6 → 1.32.7-beta.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.
package/dist/client.js CHANGED
@@ -401,10 +401,42 @@ export class PercyClient {
401
401
 
402
402
  // Retrieves snapshot/comparison data by id. Requires a read access token.
403
403
  async getStatus(type, ids) {
404
- if (!['snapshot', 'comparison'].includes(type)) throw new Error('Invalid type passed');
404
+ if (!['snapshot', 'comparison', 'intelli_story_graph'].includes(type)) throw new Error('Invalid type passed');
405
405
  this.log.debug(`Getting ${type} status for ids ${ids}`);
406
406
  return this.get(`job_status?sync=true&type=${type}&id=${ids.join()}`);
407
407
  }
408
+ async getIntelliStorySnapshotNameToCommit(buildId) {
409
+ this.log.debug('IntelliStory: looking up baselines...');
410
+ // `build_id` is the only input. The build already exists by the time this is
411
+ // called, so its base build has been selected server-side and the endpoint
412
+ // reads through to that base build's commit — there is nothing to predict
413
+ // from git/PR context any more.
414
+ const qs = new URLSearchParams();
415
+ if (buildId) qs.append('build_id', buildId);
416
+ const query = qs.toString();
417
+ return this.get(query ? `intelli_story/snapshot-name-to-commit?${query}` : 'intelli_story/snapshot-name-to-commit', {
418
+ identifier: 'intelli_story.snapshot_name_to_commit'
419
+ });
420
+ }
421
+ async generateIntelliStoryGraph(buildId, {
422
+ files,
423
+ modules,
424
+ storybookPaths,
425
+ affectedNodes,
426
+ affectedFileLocations
427
+ } = {}) {
428
+ this.log.debug(`IntelliStory: enqueueing graph build for build ${buildId}...`);
429
+ return this.post('intelli_story/generate-graph', {
430
+ build_id: buildId,
431
+ files,
432
+ modules,
433
+ storybook_paths: storybookPaths,
434
+ affected_nodes: affectedNodes,
435
+ affected_file_locations: affectedFileLocations
436
+ }, {
437
+ identifier: 'intelli_story.generate_graph'
438
+ });
439
+ }
408
440
 
409
441
  // Returns device details enabled on project associated with given token
410
442
  async getDeviceDetails(buildId) {
@@ -571,6 +603,8 @@ export class PercyClient {
571
603
  regions,
572
604
  algorithm,
573
605
  algorithmConfiguration,
606
+ intelliStory,
607
+ storybookPath,
574
608
  resources = [],
575
609
  meta
576
610
  } = {}) {
@@ -604,7 +638,11 @@ export class PercyClient {
604
638
  'enable-javascript': enableJavaScript || null,
605
639
  'enable-layout': enableLayout || false,
606
640
  'th-test-case-execution-id': thTestCaseExecutionId || null,
607
- browsers: normalizeBrowsers(browsers) || null
641
+ browsers: normalizeBrowsers(browsers) || null,
642
+ // IntelliStory: when enabled, the API selects affected snapshots
643
+ // server-side using the story's source path.
644
+ 'intelli-story': intelliStory || null,
645
+ 'storybook-path': storybookPath || null
608
646
  },
609
647
  relationships: {
610
648
  resources: {
@@ -640,23 +678,38 @@ export class PercyClient {
640
678
  // Convenience method for creating a snapshot for the active build, uploading
641
679
  // missing resources for the snapshot, and finalizing the snapshot.
642
680
  async sendSnapshot(buildId, options) {
643
- var _snapshot$data$relati;
681
+ var _snapshot$data, _snapshot$data$relati;
644
682
  let {
645
683
  meta = {}
646
684
  } = options;
647
685
  let snapshot = await this.createSnapshot(buildId, options);
686
+
687
+ // The API always creates the snapshot record now; when server-side SmartSnap
688
+ // selection skips it, the response carries `skipped-via-smartsnap: true` and
689
+ // there are no resources to upload. Tally kept vs skipped so the storybook
690
+ // flow can print an IntelliStory summary.
691
+ let skipped = !!(snapshot !== null && snapshot !== void 0 && (_snapshot$data = snapshot.data) !== null && _snapshot$data !== void 0 && (_snapshot$data = _snapshot$data.attributes) !== null && _snapshot$data !== void 0 && _snapshot$data['skipped-via-smartsnap']);
692
+ if (typeof options.intelliStory === 'boolean') {
693
+ this.intelliStoryStats ?? (this.intelliStoryStats = {
694
+ kept: 0,
695
+ skipped: 0
696
+ });
697
+ this.intelliStoryStats[skipped ? 'skipped' : 'kept'] += 1;
698
+ }
648
699
  meta.snapshotId = snapshot.data.id;
649
700
  let missing = (_snapshot$data$relati = snapshot.data.relationships) === null || _snapshot$data$relati === void 0 || (_snapshot$data$relati = _snapshot$data$relati['missing-resources']) === null || _snapshot$data$relati === void 0 ? void 0 : _snapshot$data$relati.data;
650
701
  this.log.debug(`${(missing === null || missing === void 0 ? void 0 : missing.length) || 0} Missing resources: ${options.name}...`, meta);
651
- if (missing !== null && missing !== void 0 && missing.length) {
702
+ if (skipped) {
703
+ this.log.debug('skipping resource upload because this is a intellistory skip build', meta);
704
+ } else if (missing !== null && missing !== void 0 && missing.length) {
652
705
  let resources = options.resources.reduce((acc, r) => Object.assign(acc, {
653
706
  [r.sha]: r
654
707
  }), {});
655
708
  await this.uploadResources(buildId, missing.map(({
656
709
  id
657
710
  }) => resources[id]), meta);
711
+ this.log.debug(`Resources uploaded: ${options.name}...`, meta);
658
712
  }
659
- this.log.debug(`Resources uploaded: ${options.name}...`, meta);
660
713
  await this.finalizeSnapshot(snapshot.data.id, meta);
661
714
  this.log.debug(`Finalized snapshot: ${options.name}...`, meta);
662
715
  return snapshot;
package/dist/utils.js CHANGED
@@ -239,6 +239,17 @@ export async function request(url, options = {}, callback) {
239
239
  let req = http.request(requestOptions);
240
240
  req.on('response', handleResponse);
241
241
  req.on('error', handleError);
242
+
243
+ // Node's `timeout` option only *emits* a 'timeout' event once the socket
244
+ // has been idle that long — it does not abort anything. Without this
245
+ // listener a caller passing `timeout` still waits forever on a peer that
246
+ // accepts the connection and then goes silent, and the promise never
247
+ // settles. Destroying the request surfaces it through 'error' instead.
248
+ if (requestOptions.timeout) {
249
+ req.on('timeout', () => req.destroy(Object.assign(new Error(`Request to ${url} timed out after ${requestOptions.timeout}ms`), {
250
+ code: 'ETIMEDOUT'
251
+ })));
252
+ }
242
253
  req.end(body);
243
254
  }, {
244
255
  retries,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/client",
3
- "version": "1.32.6",
3
+ "version": "1.32.7-beta.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "publishConfig": {
11
11
  "access": "public",
12
- "tag": "latest"
12
+ "tag": "beta"
13
13
  },
14
14
  "engines": {
15
15
  "node": ">=14"
@@ -33,11 +33,11 @@
33
33
  "test:coverage": "yarn test --coverage"
34
34
  },
35
35
  "dependencies": {
36
- "@percy/config": "1.32.6",
37
- "@percy/env": "1.32.6",
38
- "@percy/logger": "1.32.6",
36
+ "@percy/config": "1.32.7-beta.2",
37
+ "@percy/env": "1.32.7-beta.2",
38
+ "@percy/logger": "1.32.7-beta.2",
39
39
  "pac-proxy-agent": "^7.0.2",
40
40
  "pako": "^2.1.0"
41
41
  },
42
- "gitHead": "e7dd935acf71273fd045ccceda6d1a37db8e4600"
42
+ "gitHead": "be6a40b9d99ef190e4f6123491241c27c8308161"
43
43
  }