bdy 1.8.3-dev → 1.8.4-dev

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 (112) hide show
  1. package/distTs/bin/cli.js +5 -0
  2. package/distTs/src/agent/linux.js +119 -0
  3. package/distTs/src/agent/manager.js +395 -0
  4. package/distTs/src/agent/osx.js +139 -0
  5. package/distTs/src/agent/socket/tunnel.js +212 -0
  6. package/distTs/src/agent/socket.js +220 -0
  7. package/distTs/src/agent/system.js +177 -0
  8. package/distTs/src/agent/wait.js +23 -0
  9. package/distTs/src/agent/windows.js +159 -0
  10. package/distTs/src/agent.js +237 -0
  11. package/distTs/src/api/agent.js +84 -0
  12. package/distTs/src/api/buddy.js +117 -0
  13. package/distTs/src/api/socket.js +133 -0
  14. package/distTs/src/cfg.js +238 -0
  15. package/distTs/src/command/agent/install.js +106 -0
  16. package/distTs/src/command/agent/restart.js +27 -0
  17. package/distTs/src/command/agent/run.js +19 -0
  18. package/distTs/src/command/agent/start.js +28 -0
  19. package/distTs/src/command/agent/status.js +35 -0
  20. package/distTs/src/command/agent/stop.js +28 -0
  21. package/distTs/src/command/agent/tunnel/http.js +44 -0
  22. package/distTs/src/command/agent/tunnel/list.js +27 -0
  23. package/distTs/src/command/agent/tunnel/remove.js +28 -0
  24. package/distTs/src/command/agent/tunnel/start.js +34 -0
  25. package/distTs/src/command/agent/tunnel/status.js +31 -0
  26. package/distTs/src/command/agent/tunnel/tcp.js +43 -0
  27. package/distTs/src/command/agent/tunnel/tls.js +43 -0
  28. package/distTs/src/command/agent/tunnel.js +23 -0
  29. package/distTs/src/command/agent/uninstall.js +38 -0
  30. package/distTs/src/command/agent/update.js +38 -0
  31. package/distTs/src/command/agent/version.js +21 -0
  32. package/distTs/src/command/agent.js +29 -0
  33. package/distTs/src/command/config/add/http.js +25 -0
  34. package/distTs/src/command/config/add/tcp.js +25 -0
  35. package/distTs/src/command/config/add/tls.js +25 -0
  36. package/distTs/src/command/config/add.js +15 -0
  37. package/distTs/src/command/config/get/region.js +15 -0
  38. package/distTs/src/command/config/get/timeout.js +15 -0
  39. package/distTs/src/command/config/get/token.js +15 -0
  40. package/distTs/src/command/config/get/tunnel.js +19 -0
  41. package/distTs/src/command/config/get/tunnels.js +15 -0
  42. package/distTs/src/command/config/get/whitelist.js +15 -0
  43. package/distTs/src/command/config/get.js +21 -0
  44. package/distTs/src/command/config/remove/tunnel.js +19 -0
  45. package/distTs/src/command/config/remove.js +11 -0
  46. package/distTs/src/command/config/set/region.js +17 -0
  47. package/distTs/src/command/config/set/timeout.js +17 -0
  48. package/distTs/src/command/config/set/token.js +16 -0
  49. package/distTs/src/command/config/set/whitelist.js +17 -0
  50. package/distTs/src/command/config/set.js +17 -0
  51. package/distTs/src/command/config.js +17 -0
  52. package/distTs/src/command/http.js +30 -0
  53. package/distTs/src/command/pre.js +49 -0
  54. package/distTs/src/command/start.js +28 -0
  55. package/distTs/src/command/tcp.js +30 -0
  56. package/distTs/src/command/tls.js +30 -0
  57. package/distTs/src/command/version.js +13 -0
  58. package/distTs/src/command/vt/close.js +28 -0
  59. package/distTs/src/command/vt/exec.js +79 -0
  60. package/distTs/src/command/vt/storybook.js +90 -0
  61. package/distTs/src/command/vt.js +15 -0
  62. package/distTs/src/format.js +172 -0
  63. package/distTs/src/index.js +40 -0
  64. package/distTs/src/input.js +286 -0
  65. package/distTs/src/logger.js +93 -0
  66. package/distTs/src/output/interactive/tunnel.js +860 -0
  67. package/distTs/src/output/noninteractive/agent/tunnels.js +43 -0
  68. package/distTs/src/output/noninteractive/config/tunnel.js +67 -0
  69. package/distTs/src/output/noninteractive/config/tunnels.js +18 -0
  70. package/distTs/src/output/noninteractive/tunnel.js +59 -0
  71. package/distTs/src/output.js +138 -0
  72. package/distTs/src/server/cert.js +52 -0
  73. package/distTs/src/server/http1.js +74 -0
  74. package/distTs/src/server/http2.js +74 -0
  75. package/distTs/src/server/sftp.js +487 -0
  76. package/distTs/src/server/ssh.js +112 -0
  77. package/distTs/src/server/tls.js +41 -0
  78. package/distTs/src/ssh/client.js +191 -0
  79. package/distTs/src/texts.js +345 -0
  80. package/distTs/src/tunnel/agent.js +100 -0
  81. package/distTs/src/tunnel/compression.js +41 -0
  82. package/distTs/src/tunnel/dns.js +54 -0
  83. package/distTs/src/tunnel/html.js +30 -0
  84. package/distTs/src/tunnel/http/log.js +196 -0
  85. package/distTs/src/tunnel/http/serve.js +132 -0
  86. package/distTs/src/tunnel/http/stream.js +45 -0
  87. package/distTs/src/tunnel/http.js +405 -0
  88. package/distTs/src/tunnel/identification.js +96 -0
  89. package/distTs/src/tunnel/latency.js +71 -0
  90. package/distTs/src/tunnel/tcp.js +92 -0
  91. package/distTs/src/tunnel.js +647 -0
  92. package/distTs/src/types/ciInfo.js +10 -0
  93. package/distTs/src/types/options.js +2 -0
  94. package/distTs/src/types/plugin.js +2 -0
  95. package/distTs/src/types/queue.js +2 -0
  96. package/distTs/src/types/requests.js +2 -0
  97. package/distTs/src/types/resources.js +2 -0
  98. package/distTs/src/types/snapshots.js +2 -0
  99. package/distTs/src/types/storybook.js +2 -0
  100. package/distTs/src/utils.js +437 -0
  101. package/distTs/src/visualTest/browser.js +32 -0
  102. package/distTs/src/visualTest/ci.js +206 -0
  103. package/distTs/src/visualTest/context.js +44 -0
  104. package/distTs/src/visualTest/exec.js +51 -0
  105. package/distTs/src/visualTest/queue.js +43 -0
  106. package/distTs/src/visualTest/requests.js +197 -0
  107. package/distTs/src/visualTest/resources.js +195 -0
  108. package/distTs/src/visualTest/server.js +33 -0
  109. package/distTs/src/visualTest/snapshots.js +109 -0
  110. package/distTs/src/visualTest/utils/parseDom.js +238 -0
  111. package/distTs/src/visualTest/validation.js +18 -0
  112. package/package.json +1 -1
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.debug = exports.browserPath = exports.commitDetails = exports.invokerId = exports.executionId = exports.actionId = exports.pipelineId = exports.baseCommit = exports.commit = exports.branch = exports.ci = exports.buildId = exports.token = exports.parallel = exports.skipDiscovery = exports.oneByOne = exports.cliVersion = void 0;
4
+ exports.setOptions = setOptions;
5
+ exports.setBrowserPath = setBrowserPath;
6
+ exports.setCiAndCommitInfo = setCiAndCommitInfo;
7
+ const uuid_1 = require("uuid");
8
+ const ciInfo_js_1 = require("../types/ciInfo.js");
9
+ const utils_1 = require("../utils");
10
+ exports.cliVersion = (0, utils_1.getVersion)();
11
+ exports.oneByOne = false;
12
+ exports.skipDiscovery = false;
13
+ exports.parallel = false;
14
+ exports.token = process.env.SNAPSHOTS_TOKEN || '';
15
+ exports.buildId = process.env.SNAPSHOTS_BUILD_ID || (0, uuid_1.v4)();
16
+ exports.ci = ciInfo_js_1.CI.NONE;
17
+ exports.debug = (process.env.SNAPSHOTS_DEBUG || '').toLowerCase() === 'true';
18
+ function setOptions(options) {
19
+ if (options.oneByOne) {
20
+ exports.oneByOne = true;
21
+ }
22
+ if (options.skipDiscovery) {
23
+ exports.skipDiscovery = true;
24
+ }
25
+ if (options.parallel) {
26
+ exports.parallel = true;
27
+ }
28
+ }
29
+ function setBrowserPath(path) {
30
+ exports.browserPath = path;
31
+ }
32
+ function setCiAndCommitInfo(ciInfo) {
33
+ exports.ci = ciInfo.ci;
34
+ exports.branch = ciInfo.branch;
35
+ exports.commit = ciInfo.commit;
36
+ exports.baseCommit = ciInfo.baseCommit;
37
+ exports.commitDetails = ciInfo.commitDetails;
38
+ if (ciInfo.ci === ciInfo_js_1.CI.BUDDY) {
39
+ exports.pipelineId = ciInfo.pipelineId;
40
+ exports.actionId = ciInfo.actionId;
41
+ exports.executionId = ciInfo.executionId;
42
+ exports.invokerId = ciInfo.invokerId;
43
+ }
44
+ }
@@ -0,0 +1,51 @@
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.testExec = testExec;
7
+ exports.gitExec = gitExec;
8
+ const cross_spawn_1 = require("cross-spawn");
9
+ const output_1 = __importDefault(require("../output"));
10
+ const texts_1 = require("../texts");
11
+ function testExec(command, arguments_) {
12
+ return new Promise((resolve, reject) => {
13
+ const process = (0, cross_spawn_1.spawn)(command, arguments_, { stdio: 'inherit' });
14
+ let processError;
15
+ process.on('error', (error) => {
16
+ output_1.default.error(texts_1.ERR_TEST_EXECUTION);
17
+ processError = error;
18
+ });
19
+ process.on('close', (code) => {
20
+ if (processError) {
21
+ reject(processError);
22
+ }
23
+ else {
24
+ resolve(code || 0);
25
+ }
26
+ });
27
+ });
28
+ }
29
+ function gitExec(arguments_) {
30
+ return new Promise((resolve, reject) => {
31
+ const process = (0, cross_spawn_1.spawn)('git', arguments_, {
32
+ stdio: ['ignore', 'pipe', 'pipe'],
33
+ });
34
+ let errorOutput = '';
35
+ let output = '';
36
+ process.stdout.on('data', (message) => {
37
+ output += message;
38
+ });
39
+ process.stderr.on('data', (message) => {
40
+ errorOutput += message;
41
+ });
42
+ process.on('close', (code) => {
43
+ if (code === 0) {
44
+ resolve(output);
45
+ }
46
+ else {
47
+ reject(errorOutput);
48
+ }
49
+ });
50
+ });
51
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addToQueue = addToQueue;
4
+ exports.isQueueEmpty = isQueueEmpty;
5
+ const queue = [];
6
+ const observers = [];
7
+ let processing = false;
8
+ function addToQueue(job) {
9
+ queue.push(job);
10
+ if (!processing) {
11
+ processQueue();
12
+ }
13
+ }
14
+ function processQueue() {
15
+ const task = queue.shift();
16
+ if (task) {
17
+ processing = true;
18
+ task().then(() => {
19
+ if (queue.length > 0) {
20
+ processQueue();
21
+ }
22
+ else {
23
+ processing = false;
24
+ signalStopProcessing();
25
+ }
26
+ });
27
+ }
28
+ }
29
+ function subscribeToStopProcessing(function_) {
30
+ observers.push(function_);
31
+ }
32
+ function signalStopProcessing() {
33
+ for (const observer of observers) {
34
+ observer();
35
+ }
36
+ }
37
+ async function isQueueEmpty() {
38
+ return new Promise((resolve) => {
39
+ subscribeToStopProcessing(() => {
40
+ resolve(true);
41
+ });
42
+ });
43
+ }
@@ -0,0 +1,197 @@
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.sendSnapshot = sendSnapshot;
7
+ exports.sendSnapshots = sendSnapshots;
8
+ exports.closeSession = closeSession;
9
+ exports.getDefaultSettings = getDefaultSettings;
10
+ exports.sendStorybook = sendStorybook;
11
+ const context_js_1 = require("./context.js");
12
+ const undici_1 = require("undici");
13
+ const uuid_1 = require("uuid");
14
+ const node_fs_1 = require("node:fs");
15
+ const output_1 = __importDefault(require("../output"));
16
+ const texts_1 = require("../texts");
17
+ const serviceUrl = process.env.SNAPSHOTS_SERVICE_URL || 'http://localhost:3000';
18
+ function filterSnapshotPlugin(snapshot) {
19
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
20
+ const { resourceDiscoveryTimeout, cookies, ...filteredSnapshot } = snapshot;
21
+ return filteredSnapshot;
22
+ }
23
+ function convertTextToBlob(text, headers) {
24
+ if (headers['content-type']?.includes('image')) {
25
+ const buffer = Buffer.from(text, 'base64');
26
+ return new Blob([buffer]);
27
+ }
28
+ else {
29
+ return new Blob([text]);
30
+ }
31
+ }
32
+ function prepareSnapshot(snapshot, files) {
33
+ return {
34
+ ...filterSnapshotPlugin(snapshot),
35
+ resources: snapshot.resources.map((resource) => {
36
+ const { body, headers, ...rest } = resource;
37
+ if (body) {
38
+ const id = (0, uuid_1.v4)();
39
+ const preparedBody = typeof body === 'string' ? convertTextToBlob(body, headers) : body;
40
+ files.push({ id, body: preparedBody });
41
+ return { ...rest, headers, id };
42
+ }
43
+ return resource;
44
+ }),
45
+ };
46
+ }
47
+ function createFormData(info, files) {
48
+ const formData = new undici_1.FormData();
49
+ formData.append('info', JSON.stringify(info));
50
+ for (const { id, body } of files) {
51
+ formData.append(id, body);
52
+ }
53
+ return formData;
54
+ }
55
+ async function sendSnapshot(snapshot) {
56
+ const files = [];
57
+ const preparedSnapshot = prepareSnapshot(snapshot, files);
58
+ const info = {
59
+ snapshot: preparedSnapshot,
60
+ token: context_js_1.token,
61
+ buildId: context_js_1.buildId,
62
+ cliVersion: context_js_1.cliVersion,
63
+ parallel: context_js_1.parallel,
64
+ ci: context_js_1.ci,
65
+ branch: context_js_1.branch,
66
+ commit: context_js_1.commit,
67
+ baseCommit: context_js_1.baseCommit,
68
+ pipelineId: context_js_1.pipelineId,
69
+ actionId: context_js_1.actionId,
70
+ executionId: context_js_1.executionId,
71
+ invokerId: context_js_1.invokerId,
72
+ commitDetails: context_js_1.commitDetails,
73
+ };
74
+ const formData = createFormData(info, files);
75
+ const [message] = await sendRequest({
76
+ url: '/snapshot',
77
+ payload: formData,
78
+ multipart: true,
79
+ });
80
+ if (!message) {
81
+ throw new Error(texts_1.ERR_INVALID_SNAPSHOT_RESPONSE);
82
+ }
83
+ return message;
84
+ }
85
+ async function sendSnapshots(snapshots) {
86
+ const files = [];
87
+ const preparedSnapshots = snapshots.map((snapshot) => prepareSnapshot(snapshot, files));
88
+ const info = {
89
+ snapshots: preparedSnapshots,
90
+ token: context_js_1.token,
91
+ buildId: context_js_1.buildId,
92
+ cliVersion: context_js_1.cliVersion,
93
+ parallel: context_js_1.parallel,
94
+ ci: context_js_1.ci,
95
+ branch: context_js_1.branch,
96
+ commit: context_js_1.commit,
97
+ baseCommit: context_js_1.baseCommit,
98
+ pipelineId: context_js_1.pipelineId,
99
+ actionId: context_js_1.actionId,
100
+ executionId: context_js_1.executionId,
101
+ invokerId: context_js_1.invokerId,
102
+ commitDetails: context_js_1.commitDetails,
103
+ };
104
+ const formData = createFormData(info, files);
105
+ const [message] = await sendRequest({
106
+ url: '/snapshots',
107
+ payload: formData,
108
+ multipart: true,
109
+ });
110
+ if (!message) {
111
+ throw new Error(texts_1.ERR_INVALID_SNAPSHOTS_RESPONSE);
112
+ }
113
+ return message;
114
+ }
115
+ async function closeSession() {
116
+ const payload = {
117
+ token: context_js_1.token,
118
+ buildId: context_js_1.buildId,
119
+ };
120
+ const [message] = await sendRequest({ url: '/close', payload });
121
+ if (!message) {
122
+ throw new Error(texts_1.ERR_INVALID_CLOSE_SESSION_RESPONSE);
123
+ }
124
+ return message;
125
+ }
126
+ async function getDefaultSettings() {
127
+ const [message, response] = await sendRequest({
128
+ url: `/defaultSettings?token=${context_js_1.token}`,
129
+ });
130
+ if (message) {
131
+ throw new Error(message);
132
+ }
133
+ if (!response) {
134
+ throw new Error(texts_1.ERR_INVALID_DEFAULT_SETTINGS_RESPONSE);
135
+ }
136
+ return response;
137
+ }
138
+ async function sendStorybook(snapshots, filePaths) {
139
+ const info = {
140
+ snapshots,
141
+ token: context_js_1.token,
142
+ buildId: context_js_1.buildId,
143
+ cliVersion: context_js_1.cliVersion,
144
+ ci: context_js_1.ci,
145
+ branch: context_js_1.branch,
146
+ commit: context_js_1.commit,
147
+ baseCommit: context_js_1.baseCommit,
148
+ pipelineId: context_js_1.pipelineId,
149
+ actionId: context_js_1.actionId,
150
+ executionId: context_js_1.executionId,
151
+ invokerId: context_js_1.invokerId,
152
+ commitDetails: context_js_1.commitDetails,
153
+ };
154
+ const files = filePaths.map((file) => ({
155
+ id: file,
156
+ body: new Blob([(0, node_fs_1.readFileSync)(file)]),
157
+ }));
158
+ const formData = createFormData(info, files);
159
+ const [message] = await sendRequest({
160
+ url: '/storybook',
161
+ payload: formData,
162
+ multipart: true,
163
+ });
164
+ if (!message) {
165
+ throw new Error(texts_1.ERR_INVALID_STORYBOOK_RESPONSE);
166
+ }
167
+ return message;
168
+ }
169
+ async function sendRequest({ url, payload, multipart, }) {
170
+ output_1.default.normal((0, texts_1.LOG_SENDING_REQUEST)(`${serviceUrl}${url}`));
171
+ const init = {
172
+ method: 'GET',
173
+ redirect: 'follow',
174
+ };
175
+ if (payload && !multipart) {
176
+ init.method = 'POST';
177
+ init.headers = { 'Content-Type': 'application/json' };
178
+ init.body = JSON.stringify(payload);
179
+ }
180
+ if (multipart) {
181
+ init.method = 'POST';
182
+ init.body = payload;
183
+ }
184
+ const response = await (0, undici_1.fetch)(`${serviceUrl}${url}`, init);
185
+ const contentType = response.headers.get('content-type');
186
+ if (contentType && contentType.includes('application/json')) {
187
+ try {
188
+ const json = (await response.json());
189
+ return [undefined, json];
190
+ }
191
+ catch {
192
+ throw new Error(texts_1.ERR_INVALID_JSON);
193
+ }
194
+ }
195
+ const text = await response.text();
196
+ return [text, undefined];
197
+ }
@@ -0,0 +1,195 @@
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.collectResources = collectResources;
7
+ const puppeteer_core_1 = __importDefault(require("puppeteer-core"));
8
+ const context_js_1 = require("./context.js");
9
+ const output_1 = __importDefault(require("../output"));
10
+ const texts_1 = require("../texts");
11
+ const scrapedUrls = new Map();
12
+ const scrapedResources = new Map();
13
+ async function collectResources({ url, widths = [1280], resourceDiscoveryTimeout = 0, height = 1024, cookies, scaleRatio, }) {
14
+ const scrapedUrl = scrapedUrls.get(url);
15
+ const missingWidths = scrapedUrl
16
+ ? widths.filter((width) => !scrapedUrl.widths.includes(width))
17
+ : [];
18
+ if (scrapedUrl && missingWidths.length === 0) {
19
+ return getResourceUrlsData({
20
+ duplicatedResourcesUrls: scrapedUrl.resources,
21
+ });
22
+ }
23
+ else if (scrapedUrl && missingWidths.length > 0) {
24
+ const { scrapedResourcesUrls, duplicatedResourcesUrls } = await output_1.default.debug((0, texts_1.DEBUG_RESOURCE_SCRAPPING_URL)(url), scrapeResources({
25
+ url,
26
+ widths: missingWidths,
27
+ height,
28
+ resourceDiscoveryTimeout,
29
+ cookies,
30
+ scaleRatio,
31
+ }));
32
+ const duplicatedScrapedResourceUrls = [...scrapedUrl.resources];
33
+ scrapedUrls.set(url, {
34
+ widths: [...scrapedUrl.widths, ...missingWidths],
35
+ resources: [
36
+ ...new Set([
37
+ ...scrapedUrl.resources,
38
+ ...scrapedResourcesUrls,
39
+ ...duplicatedResourcesUrls,
40
+ ]),
41
+ ],
42
+ });
43
+ return getResourceUrlsData({
44
+ resourcesUrls: scrapedResourcesUrls,
45
+ duplicatedResourcesUrls: [
46
+ ...new Set([
47
+ ...duplicatedResourcesUrls,
48
+ ...duplicatedScrapedResourceUrls,
49
+ ]),
50
+ ],
51
+ });
52
+ }
53
+ else {
54
+ const { scrapedResourcesUrls, duplicatedResourcesUrls } = await output_1.default.debug((0, texts_1.DEBUG_RESOURCE_SCRAPPING_URL)(url), scrapeResources({
55
+ url,
56
+ widths,
57
+ height,
58
+ resourceDiscoveryTimeout,
59
+ cookies,
60
+ scaleRatio,
61
+ }));
62
+ scrapedUrls.set(url, {
63
+ widths,
64
+ resources: [...scrapedResourcesUrls, ...duplicatedResourcesUrls],
65
+ });
66
+ return getResourceUrlsData({
67
+ resourcesUrls: scrapedResourcesUrls,
68
+ duplicatedResourcesUrls,
69
+ });
70
+ }
71
+ }
72
+ function getResourceUrlsData({ resourcesUrls = [], duplicatedResourcesUrls = [], }) {
73
+ const resources = [];
74
+ for (const resourceUrl of resourcesUrls) {
75
+ const scrapedResource = scrapedResources.get(resourceUrl);
76
+ if (scrapedResource) {
77
+ resources.push({
78
+ url: resourceUrl,
79
+ status: scrapedResource.status,
80
+ headers: scrapedResource.headers,
81
+ body: scrapedResource.body,
82
+ });
83
+ }
84
+ else {
85
+ throw new Error((0, texts_1.ERR_RESOURCE_NOT_FOUND)(resourceUrl));
86
+ }
87
+ }
88
+ for (const resourceUrl of duplicatedResourcesUrls) {
89
+ const scrapedResource = scrapedResources.get(resourceUrl);
90
+ if (scrapedResource) {
91
+ resources.push({
92
+ url: resourceUrl,
93
+ status: scrapedResource.status,
94
+ headers: scrapedResource.headers,
95
+ duplicate: true,
96
+ });
97
+ }
98
+ else {
99
+ throw new Error((0, texts_1.ERR_RESOURCE_NOT_FOUND)(resourceUrl));
100
+ }
101
+ }
102
+ return resources;
103
+ }
104
+ async function scrapeResources({ url, widths, height, resourceDiscoveryTimeout, cookies = [], scaleRatio, }) {
105
+ const scrapedResourcesUrls = [];
106
+ const duplicatedResourcesUrls = [];
107
+ const launchOptions = {
108
+ headless: 'shell',
109
+ args: ['--no-sandbox'],
110
+ acceptInsecureCerts: true,
111
+ timeout: 120_000,
112
+ executablePath: context_js_1.browserPath,
113
+ };
114
+ const browser = await puppeteer_core_1.default.launch(launchOptions);
115
+ const page = await browser.newPage();
116
+ const initWidth = widths[0];
117
+ await page.setViewport({
118
+ width: initWidth,
119
+ height,
120
+ deviceScaleFactor: scaleRatio,
121
+ });
122
+ await page.setCookie(...cookies);
123
+ page.on('response', async (response) => {
124
+ const request = response.request();
125
+ const requestUrl = request.url();
126
+ const isCollected = scrapedResources.has(requestUrl);
127
+ if (isCollected && !scrapedResourcesUrls.includes(requestUrl)) {
128
+ duplicatedResourcesUrls.push(requestUrl);
129
+ }
130
+ else {
131
+ let responseError;
132
+ let body;
133
+ const requestUrl = request.url();
134
+ const headers = response.headers();
135
+ const contentType = headers['content-type'];
136
+ const status = response.status();
137
+ try {
138
+ if ((status < 300 || status > 399) &&
139
+ !contentType.startsWith('text/html')) {
140
+ body = new Blob([await response.buffer()]);
141
+ }
142
+ }
143
+ catch (error) {
144
+ responseError = error;
145
+ }
146
+ if (!responseError && body) {
147
+ scrapedResourcesUrls.push(requestUrl);
148
+ scrapedResources.set(requestUrl, {
149
+ status,
150
+ headers: { 'content-type': contentType },
151
+ body,
152
+ });
153
+ }
154
+ }
155
+ });
156
+ await page.goto(url);
157
+ await output_1.default.debug(texts_1.DEBUG_AUTO_SCROLL, autoScroll(page));
158
+ await output_1.default.debug(texts_1.DEBUG_AUTO_WIDTH, autoWidths(page, widths, height));
159
+ if (resourceDiscoveryTimeout > 0) {
160
+ await new Promise((resolve) => setTimeout(resolve, resourceDiscoveryTimeout));
161
+ if (context_js_1.debug) {
162
+ output_1.default.warning((0, texts_1.DEBUG_RESOURCE_DISCOVERY_TIMEOUT)(resourceDiscoveryTimeout));
163
+ }
164
+ }
165
+ await output_1.default.debug(texts_1.DEBUG_WAIT_FOR_IDLE, page.waitForNetworkIdle());
166
+ await browser.close();
167
+ return { scrapedResourcesUrls, duplicatedResourcesUrls };
168
+ }
169
+ async function autoScroll(page) {
170
+ await page.evaluate(async () => {
171
+ await new Promise((resolve) => {
172
+ const resourceDiscoveryMaxHeight = 30_000;
173
+ let totalHeight = 0;
174
+ const distance = 100;
175
+ const timer = setInterval(() => {
176
+ const scrollHeight = document.body.scrollHeight;
177
+ window.scrollBy(0, distance);
178
+ totalHeight += distance;
179
+ if (totalHeight >=
180
+ (scrollHeight - window.innerHeight || resourceDiscoveryMaxHeight)) {
181
+ clearInterval(timer);
182
+ resolve('');
183
+ }
184
+ }, 10);
185
+ });
186
+ });
187
+ }
188
+ async function autoWidths(page, widths, height) {
189
+ for (const width of widths) {
190
+ if (width !== widths[0]) {
191
+ await page.setViewport({ width, height, deviceScaleFactor: 2 });
192
+ await new Promise((resolve) => setTimeout(resolve, 100));
193
+ }
194
+ }
195
+ }
@@ -0,0 +1,33 @@
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.createServer = createServer;
7
+ const fastify_1 = __importDefault(require("fastify"));
8
+ const cors_1 = __importDefault(require("@fastify/cors"));
9
+ const snapshots_js_1 = require("./snapshots.js");
10
+ // File will be imported as source text;
11
+ // @ts-ignore
12
+ const parseDom_js_1 = __importDefault(require("./utils/parseDom.js"));
13
+ const port = 1337;
14
+ async function createServer() {
15
+ const app = (0, fastify_1.default)({
16
+ // logger: true,
17
+ bodyLimit: 50 * 1024 * 1024, //50 MB,
18
+ });
19
+ app.register(cors_1.default);
20
+ app.get('/parseDom.js', async (request, reply) => {
21
+ reply.type('text/js').send(parseDom_js_1.default);
22
+ });
23
+ app.post('/snapshot', async (request, reply) => {
24
+ const data = request.body;
25
+ (0, snapshots_js_1.addSnapshot)(data);
26
+ reply.send('Snapshot received');
27
+ });
28
+ app.get('*', (request, reply) => {
29
+ reply.send('Wrong path');
30
+ });
31
+ await app.listen({ port });
32
+ return app;
33
+ }
@@ -0,0 +1,109 @@
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.setDefaultSettings = setDefaultSettings;
7
+ exports.addSnapshot = addSnapshot;
8
+ exports.finishProcessingSnapshots = finishProcessingSnapshots;
9
+ const resources_js_1 = require("./resources.js");
10
+ const context_js_1 = require("./context.js");
11
+ const requests_js_1 = require("./requests.js");
12
+ const queue_js_1 = require("./queue.js");
13
+ const output_1 = __importDefault(require("../output"));
14
+ const texts_1 = require("../texts");
15
+ const snapshots = [];
16
+ let defaultWidths = [];
17
+ let defaultScaleRatio = 1;
18
+ function setDefaultSettings({ defaultWidths: width, defaultScaleRatio: scaleRatio, }) {
19
+ defaultWidths = width;
20
+ defaultScaleRatio = scaleRatio;
21
+ }
22
+ function addSnapshot(snapshot) {
23
+ const preparedSnapshots = {
24
+ ...snapshot,
25
+ widths: snapshot.widths.length > 0 ? snapshot.widths : defaultWidths,
26
+ scaleRatio: defaultScaleRatio,
27
+ };
28
+ if (context_js_1.oneByOne) {
29
+ (0, queue_js_1.addToQueue)(() => processSnapshot(preparedSnapshots));
30
+ }
31
+ else {
32
+ snapshots.push(preparedSnapshots);
33
+ }
34
+ }
35
+ async function finishProcessingSnapshots(spawnedProcessExitCode) {
36
+ if (context_js_1.oneByOne) {
37
+ return await (0, queue_js_1.isQueueEmpty)();
38
+ }
39
+ if (spawnedProcessExitCode === 0) {
40
+ return await processSnapshots();
41
+ }
42
+ }
43
+ async function processSnapshot(snapshot) {
44
+ let t1;
45
+ if (context_js_1.debug) {
46
+ t1 = performance.now();
47
+ }
48
+ const preparedSnapshot = context_js_1.skipDiscovery
49
+ ? snapshot
50
+ : await getSnapshotWithResources(snapshot);
51
+ try {
52
+ const response = await (0, requests_js_1.sendSnapshot)(preparedSnapshot);
53
+ output_1.default.normal(response);
54
+ }
55
+ catch (error) {
56
+ output_1.default.error(`${error}`);
57
+ }
58
+ if (context_js_1.debug && t1) {
59
+ const t2 = performance.now();
60
+ output_1.default.normal((0, texts_1.DEBUG_SNAPSHOT_PROCESSING)(snapshot.name, t2 - t1));
61
+ }
62
+ }
63
+ async function processSnapshots() {
64
+ let t1;
65
+ if (context_js_1.debug) {
66
+ t1 = performance.now();
67
+ }
68
+ output_1.default.normal((0, texts_1.LOG_PROCESSING_SNAPSHOTS)(snapshots.length));
69
+ const preparedSnapshots = context_js_1.skipDiscovery
70
+ ? snapshots
71
+ : await getSnapshotsWithResources(snapshots);
72
+ try {
73
+ const response = await (0, requests_js_1.sendSnapshots)(preparedSnapshots);
74
+ output_1.default.normal(response);
75
+ }
76
+ catch (error) {
77
+ output_1.default.error(`${error}`);
78
+ }
79
+ if (context_js_1.debug && t1) {
80
+ const t2 = performance.now();
81
+ output_1.default.normal((0, texts_1.DEBUG_SNAPSHOTS_PROCESSING)(t2 - t1));
82
+ }
83
+ }
84
+ async function getSnapshotWithResources(snapshot) {
85
+ const { url, widths, resourceDiscoveryTimeout, cookies, scaleRatio } = snapshot;
86
+ const resources = await (0, resources_js_1.collectResources)({
87
+ url,
88
+ widths,
89
+ resourceDiscoveryTimeout,
90
+ cookies,
91
+ scaleRatio,
92
+ });
93
+ return {
94
+ ...snapshot,
95
+ resources: [...snapshot.resources, ...resources],
96
+ };
97
+ }
98
+ async function getSnapshotsWithResources(snapshots) {
99
+ const snapshotsWithResources = [];
100
+ const prepareSnapshots = filterDuplicates(snapshots);
101
+ for (const snapshot of prepareSnapshots) {
102
+ const snapshotWithResources = await getSnapshotWithResources(snapshot);
103
+ snapshotsWithResources.push(snapshotWithResources);
104
+ }
105
+ return snapshotsWithResources;
106
+ }
107
+ function filterDuplicates(snapshots) {
108
+ return snapshots.filter((snapshot, index) => snapshots.findIndex((item) => item.name === snapshot.name) === index);
109
+ }