@percy/cli-snapshot 1.0.0 → 1.0.1

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/config.js ADDED
@@ -0,0 +1,79 @@
1
+ // Config schema for static directories
2
+ export const configSchema = {
3
+ static: {
4
+ type: 'object',
5
+ $ref: '/snapshot#/$defs/filter',
6
+ unevaluatedProperties: false,
7
+ properties: {
8
+ baseUrl: {
9
+ $ref: '/snapshot/server#/properties/baseUrl'
10
+ },
11
+ cleanUrls: {
12
+ $ref: '/snapshot/server#/properties/cleanUrls'
13
+ },
14
+ rewrites: {
15
+ $ref: '/snapshot/server#/properties/rewrites'
16
+ },
17
+ options: {
18
+ $ref: '/snapshot#/$defs/options'
19
+ }
20
+ }
21
+ },
22
+ sitemap: {
23
+ type: 'object',
24
+ $ref: '/snapshot#/$defs/filter',
25
+ unevaluatedProperties: false,
26
+ properties: {
27
+ options: {
28
+ $ref: '/snapshot#/$defs/options'
29
+ }
30
+ }
31
+ }
32
+ };
33
+ export function configMigration(config, util) {
34
+ /* eslint-disable curly */
35
+ if (config.version < 2) {
36
+ // static-snapshots and options were renamed
37
+ util.map('staticSnapshots.baseUrl', 'static.baseUrl');
38
+ util.map('staticSnapshots.snapshotFiles', 'static.include');
39
+ util.map('staticSnapshots.ignoreFiles', 'static.exclude');
40
+ util.del('staticSnapshots');
41
+ } else {
42
+ let notice = {
43
+ type: 'config',
44
+ until: '1.0.0'
45
+ }; // static files and ignore options were renamed
46
+
47
+ util.deprecate('static.files', {
48
+ map: 'static.include',
49
+ ...notice
50
+ });
51
+ util.deprecate('static.ignore', {
52
+ map: 'static.exclude',
53
+ ...notice
54
+ }); // static and sitemap option overrides were renamed
55
+
56
+ util.deprecate('static.overrides', {
57
+ map: 'static.options',
58
+ ...notice
59
+ });
60
+ util.deprecate('sitemap.overrides', {
61
+ map: 'sitemap.options',
62
+ ...notice
63
+ });
64
+
65
+ for (let i in ((_config$static = config.static) === null || _config$static === void 0 ? void 0 : _config$static.options) || []) {
66
+ var _config$static;
67
+
68
+ let k = `static.options[${i}]`;
69
+ util.deprecate(`${k}.files`, {
70
+ map: `${k}.include`,
71
+ ...notice
72
+ });
73
+ util.deprecate(`${k}.ignore`, {
74
+ map: `${k}.exclude`,
75
+ ...notice
76
+ });
77
+ }
78
+ }
79
+ }
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default, snapshot } from './snapshot.js';
@@ -0,0 +1,167 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import command from '@percy/cli-command';
4
+ import * as SnapshotConfig from './config.js';
5
+ export const snapshot = command('snapshot', {
6
+ description: 'Snapshot a static directory, snapshots file, or sitemap URL',
7
+ args: [{
8
+ name: 'dir|file|sitemap',
9
+ description: 'Static directory, snapshots file, or sitemap url',
10
+ required: true,
11
+ attribute: val => {
12
+ if (/^https?:\/\//.test(val)) return 'sitemap';
13
+ if (!fs.existsSync(val)) throw new Error(`Not found: ${val}`);
14
+ return fs.lstatSync(val).isDirectory() ? 'serve' : 'file';
15
+ }
16
+ }],
17
+ flags: [{
18
+ name: 'base-url',
19
+ description: 'The base url pages are hosted at when snapshotting',
20
+ type: 'string',
21
+ short: 'b'
22
+ }, {
23
+ name: 'include',
24
+ description: 'One or more globs/patterns matching snapshots to include',
25
+ type: 'pattern',
26
+ multiple: true
27
+ }, {
28
+ name: 'exclude',
29
+ description: 'One or more globs/patterns matching snapshots to exclude',
30
+ type: 'pattern',
31
+ multiple: true
32
+ }, {
33
+ // static only
34
+ name: 'clean-urls',
35
+ description: 'Rewrite static index and filepath URLs to be clean',
36
+ percyrc: 'static.cleanUrls',
37
+ group: 'Static'
38
+ }, {
39
+ // deprecated
40
+ name: 'files',
41
+ deprecated: ['1.0.0', '--include'],
42
+ percyrc: 'static.include',
43
+ type: 'pattern'
44
+ }, {
45
+ name: 'ignore',
46
+ deprecated: ['1.0.0', '--exclude'],
47
+ percyrc: 'static.exclude',
48
+ type: 'pattern'
49
+ }],
50
+ examples: ['$0 ./public', '$0 snapshots.yml', '$0 https://percy.io/sitemap.xml'],
51
+ percy: {
52
+ deferUploads: true
53
+ },
54
+ config: {
55
+ schemas: [SnapshotConfig.configSchema],
56
+ migrations: [SnapshotConfig.configMigration]
57
+ }
58
+ }, async function* ({
59
+ percy,
60
+ args,
61
+ flags,
62
+ log,
63
+ exit
64
+ }) {
65
+ let {
66
+ include,
67
+ exclude,
68
+ baseUrl,
69
+ cleanUrls
70
+ } = flags;
71
+ let {
72
+ file,
73
+ serve,
74
+ sitemap
75
+ } = args; // parse and validate the --base-url flag after args are parsed
76
+
77
+ if (file || serve) baseUrl && (baseUrl = parseBaseUrl(baseUrl, !!serve)); // only continue if percy is not disabled
78
+
79
+ if (!percy) exit(0, 'Percy is disabled');
80
+
81
+ try {
82
+ let options;
83
+ /* istanbul ignore else: arg is required and always one of these */
84
+
85
+ if (file) {
86
+ // load snapshots file
87
+ let snapshots = yield loadSnapshotFile(file); // accept a config object instead of an array of snapshots
88
+
89
+ let config = Array.isArray(snapshots) ? {
90
+ snapshots
91
+ } : snapshots;
92
+ options = merge(config, {
93
+ baseUrl,
94
+ include,
95
+ exclude
96
+ });
97
+ } else if (serve) {
98
+ // serve and snapshot a static directory
99
+ let config = {
100
+ serve,
101
+ cleanUrls,
102
+ baseUrl,
103
+ include,
104
+ exclude
105
+ };
106
+ options = merge(percy.config.static, config);
107
+ } else if (sitemap) {
108
+ // fetch urls to snapshot from a sitemap
109
+ let config = {
110
+ sitemap,
111
+ include,
112
+ exclude
113
+ };
114
+ options = merge(percy.config.sitemap, config);
115
+ }
116
+
117
+ yield* percy.yield.start();
118
+ yield* percy.yield.snapshot(options);
119
+ yield* percy.yield.stop();
120
+ } catch (error) {
121
+ await percy.stop(true);
122
+ throw error;
123
+ }
124
+ }); // Validates the provided `--base-url` flag and returns a `baseUrl` string if valid. The flag is
125
+ // validated and parsed differently for static directories and snapshot files.
126
+
127
+ function parseBaseUrl(baseUrl, pathOnly) {
128
+ try {
129
+ let needsHost = pathOnly && baseUrl.startsWith('/');
130
+ let url = new URL(baseUrl, needsHost ? 'http://localhost' : undefined);
131
+ return pathOnly ? url.pathname : url.href;
132
+ } catch (e) {
133
+ throw new Error("The '--base-url' flag must " + (pathOnly ? 'start with a forward slash (/) when providing a static directory' : 'include a protocol and hostname when providing a list of snapshots'));
134
+ }
135
+ } // Small shallow merge util that does not merge null or undefined values.
136
+
137
+
138
+ function merge(...objs) {
139
+ return objs.reduce((target, obj) => {
140
+ for (let k in obj) target[k] = obj[k] ?? target[k];
141
+
142
+ return target;
143
+ }, {});
144
+ } // Loads snapshot options from a js, json, or yaml file.
145
+
146
+
147
+ async function loadSnapshotFile(file) {
148
+ let ext = path.extname(file);
149
+
150
+ if (ext === '.js') {
151
+ let {
152
+ default: module
153
+ } = await import(path.resolve(file));
154
+ return typeof module === 'function' ? await module() : module;
155
+ } else if (ext === '.json') {
156
+ return JSON.parse(fs.readFileSync(file, 'utf-8'));
157
+ } else if (ext.match(/\.ya?ml$/)) {
158
+ let {
159
+ default: YAML
160
+ } = await import('yaml');
161
+ return YAML.parse(fs.readFileSync(file, 'utf-8'));
162
+ } else {
163
+ throw new Error(`Unsupported filetype: ${file}`);
164
+ }
165
+ }
166
+
167
+ export default snapshot;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/cli-snapshot",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "node": ">=14"
15
15
  },
16
16
  "files": [
17
- "./dist"
17
+ "dist"
18
18
  ],
19
19
  "main": "./dist/index.js",
20
20
  "type": "module",
@@ -32,8 +32,8 @@
32
32
  ]
33
33
  },
34
34
  "dependencies": {
35
- "@percy/cli-command": "1.0.0",
35
+ "@percy/cli-command": "1.0.1",
36
36
  "yaml": "^1.10.0"
37
37
  },
38
- "gitHead": "6df509421a60144e4f9f5d59dc57a5675372a0b2"
38
+ "gitHead": "38917e6027299d6cd86008e2ccd005d90bbf89c0"
39
39
  }