bdy 1.17.29-dev → 1.18.0-dev-scrape-869b6rbvf
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/distTs/package.json +1 -1
- package/distTs/src/api/client.js +70 -6
- package/distTs/src/command/domain/buy.js +278 -0
- package/distTs/src/command/domain/get.js +45 -0
- package/distTs/src/command/domain/list.js +27 -0
- package/distTs/src/command/domain.js +15 -0
- package/distTs/src/command/project/link.js +1 -1
- package/distTs/src/command/scrape/validation.js +157 -0
- package/distTs/src/command/{vt/scrape.js → scrape.js} +43 -93
- package/distTs/src/command/vt/close.js +1 -1
- package/distTs/src/command/vt/compare/validation.js +6 -120
- package/distTs/src/command/vt/compare.js +1 -1
- package/distTs/src/command/vt/exec.js +1 -1
- package/distTs/src/command/vt/shared/validation.js +118 -0
- package/distTs/src/command/vt/storybook.js +1 -1
- package/distTs/src/command/vt.js +0 -2
- package/distTs/src/index.js +4 -0
- package/distTs/src/output.js +22 -3
- package/distTs/src/texts.js +36 -21
- package/distTs/src/visualTest/context.js +3 -2
- package/distTs/src/visualTest/requests.js +39 -24
- package/distTs/src/visualTest/validation.js +5 -2
- package/package.json +1 -1
- package/distTs/src/command/project/get.js +0 -18
- package/distTs/src/command/project/set.js +0 -31
- package/distTs/src/command/sandbox/get/yaml.js +0 -30
|
@@ -3,49 +3,61 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const utils_1 = require("
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
7
|
const commander_1 = require("commander");
|
|
8
|
-
const texts_1 = require("
|
|
9
|
-
const validation_1 = require("
|
|
10
|
-
const output_1 = __importDefault(require("
|
|
11
|
-
const requests_1 = require("
|
|
12
|
-
const zod_1 = require("zod");
|
|
8
|
+
const texts_1 = require("../texts");
|
|
9
|
+
const validation_1 = require("../visualTest/validation");
|
|
10
|
+
const output_1 = __importDefault(require("../output"));
|
|
11
|
+
const requests_1 = require("../visualTest/requests");
|
|
13
12
|
const node_zlib_1 = require("node:zlib");
|
|
14
13
|
const tar_stream_1 = __importDefault(require("tar-stream"));
|
|
15
14
|
const promises_1 = require("node:stream/promises");
|
|
16
15
|
const node_fs_1 = require("node:fs");
|
|
17
16
|
const node_path_1 = __importDefault(require("node:path"));
|
|
18
17
|
const promises_2 = require("node:fs/promises");
|
|
18
|
+
const context_1 = require("../visualTest/context");
|
|
19
|
+
const ci_info_1 = require("@buddy-works/ci-info");
|
|
20
|
+
const validation_2 = require("./scrape/validation");
|
|
19
21
|
const commandScrape = (0, utils_1.newCommand)('scrape', texts_1.DESC_COMMAND_VT_SCRAPE);
|
|
20
|
-
commandScrape.argument('
|
|
22
|
+
commandScrape.argument('[url]', texts_1.OPTION_SCRAPE_URL);
|
|
21
23
|
commandScrape.option('--follow', texts_1.OPTION_SCRAPE_FOLLOW, false);
|
|
22
|
-
commandScrape.
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
commandScrape.option('--respectRobots', texts_1.OPTION_COMPARE_RESPECT_ROBOTS, false);
|
|
25
|
+
commandScrape.addOption(new commander_1.Option('--outputType <type>', texts_1.OPTION_SCRAPE_OUTPUT_TYPE).choices([
|
|
26
|
+
'jpeg',
|
|
27
|
+
'png',
|
|
28
|
+
'md',
|
|
29
|
+
'html',
|
|
30
|
+
]));
|
|
31
|
+
commandScrape.option('--outputTypes <json>', texts_1.OPTION_SCRAPE_OUTPUT_TYPES);
|
|
25
32
|
commandScrape.option('--quality <quality>', texts_1.OPTION_SCRAPE_QUALITY);
|
|
26
33
|
commandScrape.option('--fullPage', texts_1.OPTION_SCRAPE_FULL_PAGE, false);
|
|
27
34
|
commandScrape.option('--cssSelector <selector>', texts_1.OPTION_SCRAPE_CSS_SELECTOR);
|
|
28
35
|
commandScrape.option('--xpathSelector <selector>', texts_1.OPTION_SCRAPE_XPATH_SELECTOR);
|
|
29
|
-
commandScrape.addOption(new commander_1.Option('--
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
commandScrape.option('--
|
|
35
|
-
commandScrape.option('--
|
|
36
|
+
commandScrape.addOption(new commander_1.Option('--colorScheme <scheme>', texts_1.OPTION_SCRAPE_COLOR_SCHEME).choices([
|
|
37
|
+
'LIGHT',
|
|
38
|
+
'DARK',
|
|
39
|
+
'LIGHT_AND_DARK',
|
|
40
|
+
]));
|
|
41
|
+
commandScrape.option('--browsers <browsers>', texts_1.OPTION_SCRAPE_BROWSERS);
|
|
42
|
+
commandScrape.option('--devices <devices>', texts_1.OPTION_SCRAPE_DEVICES);
|
|
43
|
+
commandScrape.option('--waitFor <waitFors...>', texts_1.OPTION_COMPARE_WAIT_FOR);
|
|
44
|
+
commandScrape.option('--cookie <cookies...>', texts_1.OPTION_COMPARE_COOKIE);
|
|
45
|
+
commandScrape.option('--header <headers...>', texts_1.OPTION_COMPARE_HEADER);
|
|
46
|
+
commandScrape.option('--localStorage <items...>', texts_1.OPTION_SCRAPE_LOCAL_STORAGE);
|
|
36
47
|
commandScrape.option('--delay <delay>', texts_1.OPTION_SCRAPE_DELAY, '0');
|
|
37
48
|
commandScrape.option('--outputDir <dir>', texts_1.OPTION_SCRAPE_OUTPUT_DIR, '.');
|
|
38
49
|
commandScrape.action(async (inputUrl, options) => {
|
|
39
|
-
if (!(0, validation_1.checkToken)()) {
|
|
40
|
-
output_1.default.exitError(texts_1.
|
|
50
|
+
if (!(0, validation_1.checkToken)('scrape')) {
|
|
51
|
+
output_1.default.exitError(texts_1.ERR_MISSING_SCRAPE_TOKEN);
|
|
41
52
|
}
|
|
42
|
-
const { url, follow,
|
|
53
|
+
const { url, follow, respectRobots, outputTypes, outputDir, fullPage, colorScheme, browsers, devices, cookies, requestHeaders, delay, waitForSelectors, localStorage, } = (0, validation_2.validateInputAndOptions)(inputUrl, options);
|
|
43
54
|
try {
|
|
44
|
-
const
|
|
45
|
-
|
|
55
|
+
const ciAndGitInfo = await (0, ci_info_1.getCiAndGitInfo)({});
|
|
56
|
+
(0, context_1.setCiAndCommitInfo)(ciAndGitInfo);
|
|
57
|
+
const { buildId } = await (0, requests_1.sendScrap)(url, follow, respectRobots, outputTypes, fullPage, colorScheme, browsers, devices, cookies, requestHeaders, delay, waitForSelectors, localStorage);
|
|
46
58
|
const status = await watchSessionStatus(buildId);
|
|
47
59
|
if (!status.ok) {
|
|
48
|
-
output_1.default.exitError(`
|
|
60
|
+
output_1.default.exitError(`Scrape session failed: ${status.error}`);
|
|
49
61
|
}
|
|
50
62
|
output_1.default.normal('Downloading scrape package');
|
|
51
63
|
const scrapPackageStream = await (0, requests_1.downloadScrapPackage)(buildId);
|
|
@@ -81,81 +93,15 @@ commandScrape.action(async (inputUrl, options) => {
|
|
|
81
93
|
output_1.default.exitError(`${error}`);
|
|
82
94
|
}
|
|
83
95
|
});
|
|
84
|
-
function validateInputAndOptions(input, options) {
|
|
85
|
-
const urlSchema = zod_1.z.string().url();
|
|
86
|
-
const optionsSchema = zod_1.z.object({
|
|
87
|
-
follow: zod_1.z.boolean(),
|
|
88
|
-
outputType: zod_1.z.enum(['jpeg', 'png', 'md', 'html']),
|
|
89
|
-
quality: zod_1.z.coerce.number().min(1).max(100).optional(),
|
|
90
|
-
outputDir: zod_1.z.string().default('.'),
|
|
91
|
-
fullPage: zod_1.z.boolean().optional(),
|
|
92
|
-
cssSelector: zod_1.z.string().optional(),
|
|
93
|
-
xpathSelector: zod_1.z.string().optional(),
|
|
94
|
-
browser: zod_1.z.enum(['chrome', 'firefox', 'safari']),
|
|
95
|
-
viewport: zod_1.z
|
|
96
|
-
.string()
|
|
97
|
-
.refine((value) => {
|
|
98
|
-
const [width, height] = value.split('x');
|
|
99
|
-
return (width &&
|
|
100
|
-
height &&
|
|
101
|
-
!isNaN(Number(width)) &&
|
|
102
|
-
!isNaN(Number(height)) &&
|
|
103
|
-
Number(width) > 0 &&
|
|
104
|
-
Number(height) > 0);
|
|
105
|
-
}, 'Invalid viewport format, example: 1920x1080')
|
|
106
|
-
.transform((value) => {
|
|
107
|
-
const [width, height] = value.split('x');
|
|
108
|
-
return {
|
|
109
|
-
width: Number(width),
|
|
110
|
-
height: Number(height),
|
|
111
|
-
};
|
|
112
|
-
}),
|
|
113
|
-
devicePixelRatio: zod_1.z.coerce.number().min(1).max(4),
|
|
114
|
-
darkMode: zod_1.z.boolean(),
|
|
115
|
-
delay: zod_1.z.coerce.number().min(0).max(10000),
|
|
116
|
-
waitForElement: zod_1.z.string().optional(),
|
|
117
|
-
});
|
|
118
|
-
try {
|
|
119
|
-
const url = urlSchema.parse(input);
|
|
120
|
-
const { follow, outputType, quality, outputDir, fullPage, cssSelector, xpathSelector, browser, viewport, devicePixelRatio, darkMode, delay, waitForElement, } = optionsSchema.parse(options);
|
|
121
|
-
if (typeof quality === 'number' && outputType !== 'jpeg') {
|
|
122
|
-
output_1.default.exitError('Quality is only supported for jpeg output type, use --outputType jpeg');
|
|
123
|
-
}
|
|
124
|
-
if (cssSelector && xpathSelector) {
|
|
125
|
-
output_1.default.exitError('Only one of --cssSelector or --xpathSelector can be used');
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
url,
|
|
129
|
-
follow,
|
|
130
|
-
outputType,
|
|
131
|
-
quality,
|
|
132
|
-
outputDir,
|
|
133
|
-
fullPage,
|
|
134
|
-
cssSelector,
|
|
135
|
-
xpathSelector,
|
|
136
|
-
browser,
|
|
137
|
-
viewport,
|
|
138
|
-
devicePixelRatio,
|
|
139
|
-
darkMode,
|
|
140
|
-
delay,
|
|
141
|
-
waitForElement,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
catch (error) {
|
|
145
|
-
if (error instanceof zod_1.ZodError) {
|
|
146
|
-
output_1.default.exitError(error.errors.map((e) => `${e.path}: ${e.message}`).join(', '));
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
throw error;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
96
|
async function watchSessionStatus(buildId) {
|
|
154
97
|
return new Promise((resolve) => {
|
|
155
98
|
const eventSource = (0, requests_1.connectToScrapSession)(buildId);
|
|
156
99
|
eventSource.addEventListener('SESSION_STATUS', (event) => {
|
|
157
100
|
const data = JSON.parse(event.data);
|
|
158
|
-
if (data.status === '
|
|
101
|
+
if (data.status === 'STARTED') {
|
|
102
|
+
output_1.default.normal('Scrape session started');
|
|
103
|
+
}
|
|
104
|
+
else if (data.status === 'GATHER_URLS_COMPLETED') {
|
|
159
105
|
output_1.default.normal(`Gathering URLs completed, found ${data.text} URLs`);
|
|
160
106
|
}
|
|
161
107
|
else if (data.status === 'GATHER_URLS_FAILED') {
|
|
@@ -173,6 +119,10 @@ async function watchSessionStatus(buildId) {
|
|
|
173
119
|
else if (data.status === 'CREATE_PACKAGE_FAILED') {
|
|
174
120
|
output_1.default.error('Package creation failed');
|
|
175
121
|
}
|
|
122
|
+
else if (data.status === 'ERROR') {
|
|
123
|
+
eventSource.close();
|
|
124
|
+
resolve({ ok: false, error: data.text });
|
|
125
|
+
}
|
|
176
126
|
else if (data.status === 'FINISHED') {
|
|
177
127
|
eventSource.close();
|
|
178
128
|
output_1.default.normal('Scrape session finished');
|
|
@@ -10,7 +10,7 @@ const requests_1 = require("../../visualTest/requests");
|
|
|
10
10
|
const output_1 = __importDefault(require("../../output"));
|
|
11
11
|
const commandVtClose = (0, utils_1.newCommand)('close', texts_1.DESC_COMMAND_VT_CLOSE);
|
|
12
12
|
commandVtClose.action(async () => {
|
|
13
|
-
if (!(0, validation_1.checkToken)()) {
|
|
13
|
+
if (!(0, validation_1.checkToken)('vt')) {
|
|
14
14
|
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
15
15
|
}
|
|
16
16
|
if (!(0, validation_1.checkBuildId)()) {
|
|
@@ -7,7 +7,7 @@ exports.validateOptions = validateOptions;
|
|
|
7
7
|
exports.checkIfMinimalOptionsAreProvided = checkIfMinimalOptionsAreProvided;
|
|
8
8
|
const zod_1 = require("zod");
|
|
9
9
|
const output_1 = __importDefault(require("../../../output"));
|
|
10
|
-
const
|
|
10
|
+
const validation_1 = require("../shared/validation");
|
|
11
11
|
const optionsSchema = zod_1.z.object({
|
|
12
12
|
urls: zod_1.z.string().optional(),
|
|
13
13
|
sitemap: zod_1.z.string().optional(),
|
|
@@ -19,102 +19,9 @@ const optionsSchema = zod_1.z.object({
|
|
|
19
19
|
message: "Ignore option must follow pattern '[scope::]type=value' where type must be CSS or XPATH (scope is optional)",
|
|
20
20
|
}))
|
|
21
21
|
.optional()
|
|
22
|
-
.transform(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const [scopePart, ...rest] = v.split('::');
|
|
26
|
-
const [typePart, ...valuePart] = rest.join('::').split('=');
|
|
27
|
-
type = typePart;
|
|
28
|
-
value = valuePart.join('=');
|
|
29
|
-
scope = scopePart;
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
const [typePart, ...valuePart] = v.split('=');
|
|
33
|
-
type = typePart;
|
|
34
|
-
value = valuePart.join('=');
|
|
35
|
-
scope = DEFAULT_SCOPE;
|
|
36
|
-
}
|
|
37
|
-
return { scope, type, value };
|
|
38
|
-
})),
|
|
39
|
-
cookie: zod_1.z
|
|
40
|
-
.array(zod_1.z
|
|
41
|
-
.string()
|
|
42
|
-
.max(4096, {
|
|
43
|
-
message: 'Cookie must be less than 4096 characters',
|
|
44
|
-
})
|
|
45
|
-
.regex(/^(?:([^:]+)::)?(.+)$/, {
|
|
46
|
-
message: "Cookie option must follow pattern '[scope::]cookie_value' (scope is optional)",
|
|
47
|
-
}))
|
|
48
|
-
.optional()
|
|
49
|
-
.transform((value) => value?.map((v) => {
|
|
50
|
-
let scope = DEFAULT_SCOPE;
|
|
51
|
-
let cookieValue = v;
|
|
52
|
-
if (v.includes('::')) {
|
|
53
|
-
const [scopePart, valuePart] = v.split('::');
|
|
54
|
-
scope = scopePart.trim();
|
|
55
|
-
cookieValue = valuePart.trim();
|
|
56
|
-
}
|
|
57
|
-
// Parse cookie string into components
|
|
58
|
-
const cookieParts = cookieValue.split(';').map((part) => part.trim());
|
|
59
|
-
const mainPart = cookieParts[0].split('=');
|
|
60
|
-
const key = mainPart[0].trim();
|
|
61
|
-
const value = mainPart[1].trim();
|
|
62
|
-
const cookie = {
|
|
63
|
-
scope,
|
|
64
|
-
key,
|
|
65
|
-
value,
|
|
66
|
-
httpOnly: false,
|
|
67
|
-
secure: false,
|
|
68
|
-
};
|
|
69
|
-
// Process additional cookie attributes
|
|
70
|
-
for (let i = 1; i < cookieParts.length; i++) {
|
|
71
|
-
const part = cookieParts[i].toLowerCase();
|
|
72
|
-
if (part === 'httponly') {
|
|
73
|
-
cookie.httpOnly = true;
|
|
74
|
-
}
|
|
75
|
-
else if (part === 'secure') {
|
|
76
|
-
cookie.secure = true;
|
|
77
|
-
}
|
|
78
|
-
else if (part.startsWith('domain=')) {
|
|
79
|
-
cookie.domain = part.substring(7);
|
|
80
|
-
}
|
|
81
|
-
else if (part.startsWith('path=')) {
|
|
82
|
-
cookie.path = part.substring(5);
|
|
83
|
-
}
|
|
84
|
-
else if (part.startsWith('samesite=')) {
|
|
85
|
-
const sameSiteValue = part.substring(9);
|
|
86
|
-
if (['strict', 'lax', 'none'].includes(sameSiteValue.toLowerCase())) {
|
|
87
|
-
cookie.sameSite = (sameSiteValue.charAt(0).toUpperCase() +
|
|
88
|
-
sameSiteValue.slice(1).toLowerCase());
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return cookie;
|
|
93
|
-
})),
|
|
94
|
-
header: zod_1.z
|
|
95
|
-
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?(.+)$/, {
|
|
96
|
-
message: "Header option must follow pattern '[scope::]header_value' (scope is optional)",
|
|
97
|
-
}))
|
|
98
|
-
.optional()
|
|
99
|
-
.transform((value) => value?.map((v) => {
|
|
100
|
-
if (v.includes('::')) {
|
|
101
|
-
const [scope, headerValue] = v.split('::');
|
|
102
|
-
const [name, value] = headerValue.split('=');
|
|
103
|
-
return {
|
|
104
|
-
scope: scope.trim(),
|
|
105
|
-
key: name.trim(),
|
|
106
|
-
value: value.trim(),
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
const [name, value] = v.split('=');
|
|
111
|
-
return {
|
|
112
|
-
scope: DEFAULT_SCOPE,
|
|
113
|
-
key: name.trim(),
|
|
114
|
-
value: value.trim(),
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
})),
|
|
22
|
+
.transform(validation_1.parseScopedSelector),
|
|
23
|
+
cookie: validation_1.cookieSchema,
|
|
24
|
+
header: validation_1.headerSchema,
|
|
118
25
|
delay: zod_1.z
|
|
119
26
|
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?(\d+)$/, {
|
|
120
27
|
message: "Delay option must follow pattern '[scope::]milliseconds' (scope is optional)",
|
|
@@ -126,31 +33,10 @@ const optionsSchema = zod_1.z.object({
|
|
|
126
33
|
return { scope: scope.trim(), value: Number(milliseconds) };
|
|
127
34
|
}
|
|
128
35
|
else {
|
|
129
|
-
return { scope: DEFAULT_SCOPE, value: Number(v) };
|
|
130
|
-
}
|
|
131
|
-
})),
|
|
132
|
-
waitFor: zod_1.z
|
|
133
|
-
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?(?:(CSS|XPATH))=(.+)$/, {
|
|
134
|
-
message: "WaitFor option must follow pattern '[scope::]type=value' where type must be CSS or XPATH (scope is optional)",
|
|
135
|
-
}))
|
|
136
|
-
.optional()
|
|
137
|
-
.transform((value) => value?.map((v) => {
|
|
138
|
-
let scope, type, value;
|
|
139
|
-
if (v.includes('::CSS=') || v.includes('::XPATH=')) {
|
|
140
|
-
const [scopePart, ...rest] = v.split('::');
|
|
141
|
-
const [typePart, ...valuePart] = rest.join('::').split('=');
|
|
142
|
-
type = typePart;
|
|
143
|
-
value = valuePart.join('=');
|
|
144
|
-
scope = scopePart;
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
const [typePart, ...valuePart] = v.split('=');
|
|
148
|
-
type = typePart;
|
|
149
|
-
value = valuePart.join('=');
|
|
150
|
-
scope = DEFAULT_SCOPE;
|
|
36
|
+
return { scope: validation_1.DEFAULT_SCOPE, value: Number(v) };
|
|
151
37
|
}
|
|
152
|
-
return { scope, type, value };
|
|
153
38
|
})),
|
|
39
|
+
waitFor: validation_1.waitForSchema,
|
|
154
40
|
ignoreUrls: zod_1.z.array(zod_1.z.string()).optional(),
|
|
155
41
|
dryRun: zod_1.z.boolean().optional(),
|
|
156
42
|
});
|
|
@@ -28,7 +28,7 @@ commandVtCompare.option('--delay <delays...>', texts_1.OPTION_COMPARE_DELAY);
|
|
|
28
28
|
commandVtCompare.option('--waitFor <waitFors...>', texts_1.OPTION_COMPARE_WAIT_FOR);
|
|
29
29
|
commandVtCompare.action(async (options) => {
|
|
30
30
|
const validatedOptions = (0, validation_2.validateOptions)(options);
|
|
31
|
-
if (!(0, validation_1.checkToken)()) {
|
|
31
|
+
if (!(0, validation_1.checkToken)('vt')) {
|
|
32
32
|
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
33
33
|
}
|
|
34
34
|
if (!(0, validation_2.checkIfMinimalOptionsAreProvided)(validatedOptions)) {
|
|
@@ -29,7 +29,7 @@ commandVtExec.action(async (command, options) => {
|
|
|
29
29
|
catch (error) {
|
|
30
30
|
output_1.default.exitError(`${error}`);
|
|
31
31
|
}
|
|
32
|
-
if (!(0, validation_1.checkToken)()) {
|
|
32
|
+
if (!(0, validation_1.checkToken)('vt')) {
|
|
33
33
|
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
34
34
|
}
|
|
35
35
|
if (!(0, validation_1.checkParallel)()) {
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
exports.waitForSchema = exports.headerSchema = exports.cookieSchema = exports.DEFAULT_SCOPE = void 0;
|
|
7
|
+
exports.parseScopedSelector = parseScopedSelector;
|
|
8
|
+
exports.parseScopedKeyValue = parseScopedKeyValue;
|
|
9
|
+
const zod_1 = require("zod");
|
|
10
|
+
const output_1 = __importDefault(require("../../../output"));
|
|
11
|
+
exports.DEFAULT_SCOPE = '**';
|
|
12
|
+
function parseScopedSelector(value) {
|
|
13
|
+
return value?.map((v) => {
|
|
14
|
+
let scope, type, selectorValue;
|
|
15
|
+
if (v.includes('::CSS=') || v.includes('::XPATH=')) {
|
|
16
|
+
const [scopePart, ...rest] = v.split('::');
|
|
17
|
+
const [typePart, ...valuePart] = rest.join('::').split('=');
|
|
18
|
+
type = typePart;
|
|
19
|
+
selectorValue = valuePart.join('=');
|
|
20
|
+
scope = scopePart;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const [typePart, ...valuePart] = v.split('=');
|
|
24
|
+
type = typePart;
|
|
25
|
+
selectorValue = valuePart.join('=');
|
|
26
|
+
scope = exports.DEFAULT_SCOPE;
|
|
27
|
+
}
|
|
28
|
+
return { scope, type, value: selectorValue };
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function parseScopedKeyValue(rawValue) {
|
|
32
|
+
let scope = exports.DEFAULT_SCOPE;
|
|
33
|
+
let keyValue = rawValue;
|
|
34
|
+
const scopeSeparatorIndex = rawValue.indexOf('::');
|
|
35
|
+
if (scopeSeparatorIndex >= 0) {
|
|
36
|
+
scope = rawValue.slice(0, scopeSeparatorIndex).trim();
|
|
37
|
+
keyValue = rawValue.slice(scopeSeparatorIndex + 2).trim();
|
|
38
|
+
}
|
|
39
|
+
const equalSignIndex = keyValue.indexOf('=');
|
|
40
|
+
if (equalSignIndex <= 0) {
|
|
41
|
+
output_1.default.exitError("Option value must follow pattern '[scope::]key=value' (scope is optional)");
|
|
42
|
+
}
|
|
43
|
+
const key = keyValue.slice(0, equalSignIndex).trim();
|
|
44
|
+
const value = keyValue.slice(equalSignIndex + 1).trim();
|
|
45
|
+
if (!key) {
|
|
46
|
+
output_1.default.exitError('Option key cannot be empty');
|
|
47
|
+
}
|
|
48
|
+
return { scope, key, value };
|
|
49
|
+
}
|
|
50
|
+
exports.cookieSchema = zod_1.z
|
|
51
|
+
.array(zod_1.z
|
|
52
|
+
.string()
|
|
53
|
+
.max(4096, {
|
|
54
|
+
message: 'Cookie must be less than 4096 characters',
|
|
55
|
+
})
|
|
56
|
+
.regex(/^(?:([^:]+)::)?([^=]+)=(.*)$/, {
|
|
57
|
+
message: "Cookie option must follow pattern '[scope::]key=value[;attribute]' (scope is optional)",
|
|
58
|
+
}))
|
|
59
|
+
.optional()
|
|
60
|
+
.transform((value) => value?.map((v) => {
|
|
61
|
+
let scope = exports.DEFAULT_SCOPE;
|
|
62
|
+
let cookieValue = v;
|
|
63
|
+
if (v.includes('::')) {
|
|
64
|
+
const [scopePart, valuePart] = v.split('::');
|
|
65
|
+
scope = scopePart.trim();
|
|
66
|
+
cookieValue = valuePart.trim();
|
|
67
|
+
}
|
|
68
|
+
const cookieParts = cookieValue.split(';').map((part) => part.trim());
|
|
69
|
+
const mainPart = cookieParts[0];
|
|
70
|
+
const firstEqualSignIndex = mainPart.indexOf('=');
|
|
71
|
+
const key = mainPart.slice(0, firstEqualSignIndex).trim();
|
|
72
|
+
const value = mainPart.slice(firstEqualSignIndex + 1).trim();
|
|
73
|
+
const cookie = {
|
|
74
|
+
scope,
|
|
75
|
+
key,
|
|
76
|
+
value,
|
|
77
|
+
httpOnly: false,
|
|
78
|
+
secure: false,
|
|
79
|
+
};
|
|
80
|
+
for (let i = 1; i < cookieParts.length; i++) {
|
|
81
|
+
const part = cookieParts[i].toLowerCase();
|
|
82
|
+
if (part === 'httponly') {
|
|
83
|
+
cookie.httpOnly = true;
|
|
84
|
+
}
|
|
85
|
+
else if (part === 'secure') {
|
|
86
|
+
cookie.secure = true;
|
|
87
|
+
}
|
|
88
|
+
else if (part.startsWith('domain=')) {
|
|
89
|
+
cookie.domain = part.substring(7);
|
|
90
|
+
}
|
|
91
|
+
else if (part.startsWith('path=')) {
|
|
92
|
+
cookie.path = part.substring(5);
|
|
93
|
+
}
|
|
94
|
+
else if (part.startsWith('samesite=')) {
|
|
95
|
+
const sameSiteValue = part.substring(9);
|
|
96
|
+
if (['strict', 'lax', 'none'].includes(sameSiteValue)) {
|
|
97
|
+
cookie.sameSite = (sameSiteValue.charAt(0).toUpperCase() +
|
|
98
|
+
sameSiteValue.slice(1));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return cookie;
|
|
103
|
+
}));
|
|
104
|
+
exports.headerSchema = zod_1.z
|
|
105
|
+
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?([^=]+)=(.*)$/, {
|
|
106
|
+
message: "Header option must follow pattern '[scope::]key=value' (scope is optional)",
|
|
107
|
+
}))
|
|
108
|
+
.optional()
|
|
109
|
+
.transform((value) => value?.map((v) => {
|
|
110
|
+
const { scope, key, value } = parseScopedKeyValue(v);
|
|
111
|
+
return { scope, key, value };
|
|
112
|
+
}));
|
|
113
|
+
exports.waitForSchema = zod_1.z
|
|
114
|
+
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?(?:(CSS|XPATH))=(.+)$/, {
|
|
115
|
+
message: "WaitFor option must follow pattern '[scope::]type=value' where type must be CSS or XPATH (scope is optional)",
|
|
116
|
+
}))
|
|
117
|
+
.optional()
|
|
118
|
+
.transform(parseScopedSelector);
|
|
@@ -17,7 +17,7 @@ const tar_stream_1 = __importDefault(require("tar-stream"));
|
|
|
17
17
|
const node_zlib_1 = require("node:zlib");
|
|
18
18
|
const commandVtStorybook = (0, utils_1.newCommand)('storybook', texts_1.DESC_COMMAND_VT_STORYBOOK);
|
|
19
19
|
commandVtStorybook.action(async () => {
|
|
20
|
-
if (!(0, validation_1.checkToken)()) {
|
|
20
|
+
if (!(0, validation_1.checkToken)('vt')) {
|
|
21
21
|
output_1.default.exitError(texts_1.ERR_MISSING_VT_TOKEN);
|
|
22
22
|
}
|
|
23
23
|
const currentDirectoryFiles = getCurrentDirectoryFiles();
|
package/distTs/src/command/vt.js
CHANGED
|
@@ -10,7 +10,6 @@ const storybook_1 = __importDefault(require("./vt/storybook"));
|
|
|
10
10
|
const exec_1 = __importDefault(require("./vt/exec"));
|
|
11
11
|
const installBrowser_1 = __importDefault(require("./vt/installBrowser"));
|
|
12
12
|
const compare_1 = __importDefault(require("./vt/compare"));
|
|
13
|
-
const scrape_1 = __importDefault(require("./vt/scrape"));
|
|
14
13
|
const commandVt = (0, utils_1.newCommand)('visual', texts_1.DESC_COMMAND_VT);
|
|
15
14
|
commandVt.alias('vt');
|
|
16
15
|
commandVt.addCommand(close_1.default);
|
|
@@ -18,5 +17,4 @@ commandVt.addCommand(storybook_1.default);
|
|
|
18
17
|
commandVt.addCommand(exec_1.default);
|
|
19
18
|
commandVt.addCommand(installBrowser_1.default);
|
|
20
19
|
commandVt.addCommand(compare_1.default);
|
|
21
|
-
commandVt.addCommand(scrape_1.default);
|
|
22
20
|
exports.default = commandVt;
|
package/distTs/src/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const stream_1 = __importDefault(require("stream"));
|
|
|
12
12
|
const utils_1 = require("./utils");
|
|
13
13
|
const texts_1 = require("./texts");
|
|
14
14
|
const vt_1 = __importDefault(require("./command/vt"));
|
|
15
|
+
const scrape_1 = __importDefault(require("./command/scrape"));
|
|
15
16
|
const ut_1 = __importDefault(require("./command/ut"));
|
|
16
17
|
const tunnel_1 = __importDefault(require("./command/tunnel"));
|
|
17
18
|
const pipeline_1 = __importDefault(require("./command/pipeline"));
|
|
@@ -25,6 +26,7 @@ const package_1 = __importDefault(require("./command/package"));
|
|
|
25
26
|
const api_1 = __importDefault(require("./command/api"));
|
|
26
27
|
const autocomplete_1 = __importDefault(require("./autocomplete"));
|
|
27
28
|
const autocomplete_2 = __importDefault(require("./command/autocomplete"));
|
|
29
|
+
const domain_1 = __importDefault(require("./command/domain"));
|
|
28
30
|
stream_1.default.setDefaultHighWaterMark(false, 67108864);
|
|
29
31
|
process.title = 'bdy';
|
|
30
32
|
process.on('uncaughtException', (err) => {
|
|
@@ -41,10 +43,12 @@ if (!(0, utils_1.isDocker)())
|
|
|
41
43
|
program.addCommand(agent_1.default);
|
|
42
44
|
program.addCommand(version_1.default);
|
|
43
45
|
program.addCommand(vt_1.default);
|
|
46
|
+
program.addCommand(scrape_1.default);
|
|
44
47
|
program.addCommand(ut_1.default);
|
|
45
48
|
program.addCommand(pipeline_1.default);
|
|
46
49
|
program.addCommand(package_1.default);
|
|
47
50
|
program.addCommand(sandbox_1.default);
|
|
51
|
+
program.addCommand(domain_1.default);
|
|
48
52
|
program.addCommand(login_1.default);
|
|
49
53
|
program.addCommand(whoami_1.default);
|
|
50
54
|
program.addCommand(logout_1.default);
|
package/distTs/src/output.js
CHANGED
|
@@ -66,9 +66,15 @@ class Output {
|
|
|
66
66
|
static getOkSign() {
|
|
67
67
|
return '✔ ';
|
|
68
68
|
}
|
|
69
|
+
static getArrowSign() {
|
|
70
|
+
return '→ ';
|
|
71
|
+
}
|
|
69
72
|
static okSign(newLine = false) {
|
|
70
73
|
return this.cyan(this.getOkSign(), newLine);
|
|
71
74
|
}
|
|
75
|
+
static arrowSign(newLine = false) {
|
|
76
|
+
return this.cyan(this.getArrowSign(), newLine);
|
|
77
|
+
}
|
|
72
78
|
static exitSuccess(msg) {
|
|
73
79
|
this.exitNormal(this.getGreenColor(msg));
|
|
74
80
|
}
|
|
@@ -280,14 +286,27 @@ class Output {
|
|
|
280
286
|
else {
|
|
281
287
|
this.cyan('? ', false);
|
|
282
288
|
this.normal(message, false);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
289
|
+
const item = items.find((item) => !prompts_1.default.Separator.isSeparator(item) && !item.disabled);
|
|
290
|
+
if (item && item.name && item.value) {
|
|
291
|
+
this.cyan(` ${item.name}`);
|
|
292
|
+
return item.value;
|
|
286
293
|
}
|
|
287
294
|
this.normal('');
|
|
288
295
|
return '';
|
|
289
296
|
}
|
|
290
297
|
}
|
|
298
|
+
static createMenuSeparator(text) {
|
|
299
|
+
return new prompts_1.default.Separator(text);
|
|
300
|
+
}
|
|
301
|
+
static createMenuItem(name, value, description) {
|
|
302
|
+
const item = {
|
|
303
|
+
name,
|
|
304
|
+
value,
|
|
305
|
+
};
|
|
306
|
+
if (description)
|
|
307
|
+
item.description = description;
|
|
308
|
+
return item;
|
|
309
|
+
}
|
|
291
310
|
static async inputMenu(message, items) {
|
|
292
311
|
if (this.isStdInTTY()) {
|
|
293
312
|
return await prompts_1.default.select({
|