@blitzbrowser/blitzbrowser 1.0.0
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/.eslintrc.js +25 -0
- package/.prettierrc +4 -0
- package/Dockerfile +26 -0
- package/LICENSE +201 -0
- package/README.md +1 -0
- package/dist/app.module.d.ts +2 -0
- package/dist/app.module.js +51 -0
- package/dist/app.module.js.map +1 -0
- package/dist/components/browser-instance.component.d.ts +53 -0
- package/dist/components/browser-instance.component.js +373 -0
- package/dist/components/browser-instance.component.js.map +1 -0
- package/dist/components/browser-instance.process.d.ts +1 -0
- package/dist/components/browser-instance.process.js +174 -0
- package/dist/components/browser-instance.process.js.map +1 -0
- package/dist/controllers/cdp.controller.d.ts +17 -0
- package/dist/controllers/cdp.controller.js +122 -0
- package/dist/controllers/cdp.controller.js.map +1 -0
- package/dist/controllers/pool-status.controller.d.ts +10 -0
- package/dist/controllers/pool-status.controller.js +38 -0
- package/dist/controllers/pool-status.controller.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +10 -0
- package/dist/main.js.map +1 -0
- package/dist/services/browser-pool.service.d.ts +36 -0
- package/dist/services/browser-pool.service.js +128 -0
- package/dist/services/browser-pool.service.js.map +1 -0
- package/dist/services/timezone.service.d.ts +6 -0
- package/dist/services/timezone.service.js +64 -0
- package/dist/services/timezone.service.js.map +1 -0
- package/dist/services/user-data.service.d.ts +15 -0
- package/dist/services/user-data.service.js +107 -0
- package/dist/services/user-data.service.js.map +1 -0
- package/dist/transforms/limit-stream.d.ts +7 -0
- package/dist/transforms/limit-stream.js +22 -0
- package/dist/transforms/limit-stream.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/docker-compose.yml +23 -0
- package/nest-cli.json +8 -0
- package/package.json +68 -0
- package/src/app.module.ts +39 -0
- package/src/components/browser-instance.component.ts +534 -0
- package/src/components/browser-instance.process.ts +193 -0
- package/src/controllers/cdp.controller.ts +122 -0
- package/src/controllers/pool-status.controller.ts +18 -0
- package/src/main.ts +9 -0
- package/src/services/browser-pool.service.ts +139 -0
- package/src/services/timezone.service.ts +42 -0
- package/src/services/user-data.service.ts +111 -0
- package/src/transforms/limit-stream.ts +30 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
12
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
13
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
14
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
15
|
+
};
|
|
16
|
+
var _CDPController_instances, _a, _CDPController_logger, _CDPController_parseConnectionOptionQueryParams;
|
|
17
|
+
var CDPController_1;
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.CDPController = exports.USER_DATA_READ_ONLY_QUERY_PARAM = exports.USER_DATA_ID_QUERY_PARAM = exports.TIMEZONE_QUERY_PARAM = exports.PROXY_URL_QUERY_PARAM = void 0;
|
|
20
|
+
const common_1 = require("@nestjs/common");
|
|
21
|
+
const core_1 = require("@nestjs/core");
|
|
22
|
+
const browser_instance_component_1 = require("../components/browser-instance.component");
|
|
23
|
+
const browser_pool_service_1 = require("../services/browser-pool.service");
|
|
24
|
+
const ws_1 = require("ws");
|
|
25
|
+
const zod_1 = require("zod");
|
|
26
|
+
const tunnel_1 = require("@blitzbrowser/tunnel");
|
|
27
|
+
exports.PROXY_URL_QUERY_PARAM = 'proxyUrl';
|
|
28
|
+
exports.TIMEZONE_QUERY_PARAM = 'timezone';
|
|
29
|
+
exports.USER_DATA_ID_QUERY_PARAM = 'userDataId';
|
|
30
|
+
exports.USER_DATA_READ_ONLY_QUERY_PARAM = 'userDataReadOnly';
|
|
31
|
+
const ConnectionOptionQueryParams = zod_1.default.object({
|
|
32
|
+
proxy_url: zod_1.default.url().optional(),
|
|
33
|
+
timezone: zod_1.default.string().optional(),
|
|
34
|
+
user_data_id: zod_1.default.string().optional(),
|
|
35
|
+
user_data_read_only: zod_1.default.boolean().optional().default(false),
|
|
36
|
+
});
|
|
37
|
+
let CDPController = CDPController_1 = _a = class CDPController {
|
|
38
|
+
constructor(browser_pool_service, http_adapter_host) {
|
|
39
|
+
_CDPController_instances.add(this);
|
|
40
|
+
this.browser_pool_service = browser_pool_service;
|
|
41
|
+
this.http_adapter_host = http_adapter_host;
|
|
42
|
+
_CDPController_logger.set(this, new common_1.Logger(CDPController_1.name));
|
|
43
|
+
}
|
|
44
|
+
async onModuleInit() {
|
|
45
|
+
const websocket_server = new ws_1.WebSocketServer({ server: this.http_adapter_host.httpAdapter.getHttpServer() });
|
|
46
|
+
websocket_server.on('connection', (cdp_websocket_client, req) => {
|
|
47
|
+
try {
|
|
48
|
+
const url = new URL(`http://127.0.0.1${req.url}`);
|
|
49
|
+
const parsed_connection_options = __classPrivateFieldGet(this, _CDPController_instances, "m", _CDPController_parseConnectionOptionQueryParams).call(this, url);
|
|
50
|
+
if (!parsed_connection_options.success) {
|
|
51
|
+
cdp_websocket_client.close(CDPController_1.BAD_REQUEST_CODE, parsed_connection_options.error.message.trim());
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const browser_instance = this.browser_pool_service.createBrowserInstance();
|
|
55
|
+
const tunnel = new tunnel_1.Tunnel();
|
|
56
|
+
tunnel.on('message', message => {
|
|
57
|
+
if (message.channel_id === browser_instance_component_1.BrowserInstance.CDP_CHANNEL_ID) {
|
|
58
|
+
cdp_websocket_client.send(message.data.toString('utf8'), { binary: false });
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
tunnel.once('closed', () => {
|
|
62
|
+
cdp_websocket_client.close();
|
|
63
|
+
});
|
|
64
|
+
cdp_websocket_client.on('message', message => {
|
|
65
|
+
tunnel.receiveMessage(tunnel_1.Message.of(browser_instance_component_1.BrowserInstance.CDP_CHANNEL_ID, message.toString('utf8')));
|
|
66
|
+
});
|
|
67
|
+
const ping_interval_id = setInterval(() => {
|
|
68
|
+
cdp_websocket_client.ping();
|
|
69
|
+
}, 3000);
|
|
70
|
+
cdp_websocket_client.on('close', () => {
|
|
71
|
+
clearInterval(ping_interval_id);
|
|
72
|
+
tunnel.close();
|
|
73
|
+
});
|
|
74
|
+
cdp_websocket_client.on('error', err => {
|
|
75
|
+
__classPrivateFieldGet(this, _CDPController_logger, "f").error(`Error with cdp websocket.`, err?.stack || err);
|
|
76
|
+
});
|
|
77
|
+
browser_instance.connectTunnel(tunnel);
|
|
78
|
+
tunnel.receiveMessage(tunnel_1.Message.of(browser_instance_component_1.BrowserInstance.EVENT_CHANNEL_ID, JSON.stringify({
|
|
79
|
+
type: 'CONNECTION_OPTIONS',
|
|
80
|
+
options: {
|
|
81
|
+
...parsed_connection_options.data
|
|
82
|
+
}
|
|
83
|
+
})));
|
|
84
|
+
__classPrivateFieldGet(this, _CDPController_logger, "f").log('Sent connection options');
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
__classPrivateFieldGet(this, _CDPController_logger, "f").error(`Error while handling client websocket.`, e?.stack || e);
|
|
88
|
+
cdp_websocket_client.close(CDPController_1.INTERNAL_SERVER_ERROR_CODE, e?.stack || e);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
websocket_server.once('close', () => {
|
|
93
|
+
this.browser_pool_service.shutdown();
|
|
94
|
+
});
|
|
95
|
+
websocket_server.once('error', (err) => {
|
|
96
|
+
__classPrivateFieldGet(this, _CDPController_logger, "f").error('Error with server websocket.', err?.stack || err);
|
|
97
|
+
this.browser_pool_service.shutdown();
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
getQueryParamValue(param, url) {
|
|
101
|
+
return url.searchParams.has(param) ? url.searchParams.get(param) : undefined;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
exports.CDPController = CDPController;
|
|
105
|
+
_CDPController_logger = new WeakMap();
|
|
106
|
+
_CDPController_instances = new WeakSet();
|
|
107
|
+
_CDPController_parseConnectionOptionQueryParams = function _CDPController_parseConnectionOptionQueryParams(url) {
|
|
108
|
+
return ConnectionOptionQueryParams.safeParse({
|
|
109
|
+
timezone: this.getQueryParamValue(exports.TIMEZONE_QUERY_PARAM, url),
|
|
110
|
+
proxy_url: this.getQueryParamValue(exports.PROXY_URL_QUERY_PARAM, url),
|
|
111
|
+
user_data_id: this.getQueryParamValue(exports.USER_DATA_ID_QUERY_PARAM, url),
|
|
112
|
+
user_data_read_only: this.getQueryParamValue(exports.USER_DATA_READ_ONLY_QUERY_PARAM, url)?.toLowerCase() === 'true',
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
CDPController.INTERNAL_SERVER_ERROR_CODE = 4000;
|
|
116
|
+
CDPController.BAD_REQUEST_CODE = 4002;
|
|
117
|
+
exports.CDPController = CDPController = CDPController_1 = __decorate([
|
|
118
|
+
(0, common_1.Controller)(),
|
|
119
|
+
__metadata("design:paramtypes", [browser_pool_service_1.BrowserPoolService,
|
|
120
|
+
core_1.HttpAdapterHost])
|
|
121
|
+
], CDPController);
|
|
122
|
+
//# sourceMappingURL=cdp.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdp.controller.js","sourceRoot":"","sources":["../../src/controllers/cdp.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BrowserPoolService } from 'src/services/browser-pool.service';
|
|
2
|
+
export declare class PoolStatusController {
|
|
3
|
+
private readonly pool_service;
|
|
4
|
+
constructor(pool_service: BrowserPoolService);
|
|
5
|
+
getStatus(): {
|
|
6
|
+
sigterm_received: boolean;
|
|
7
|
+
browsers_running: number;
|
|
8
|
+
max_browsers: number;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PoolStatusController = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const browser_pool_service_1 = require("../services/browser-pool.service");
|
|
15
|
+
let PoolStatusController = class PoolStatusController {
|
|
16
|
+
constructor(pool_service) {
|
|
17
|
+
this.pool_service = pool_service;
|
|
18
|
+
}
|
|
19
|
+
getStatus() {
|
|
20
|
+
return {
|
|
21
|
+
sigterm_received: this.pool_service.sigterm_received,
|
|
22
|
+
browsers_running: this.pool_service.nb_browser_instances_alive,
|
|
23
|
+
max_browsers: this.pool_service.max_browser_instances,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.PoolStatusController = PoolStatusController;
|
|
28
|
+
__decorate([
|
|
29
|
+
(0, common_1.Get)(),
|
|
30
|
+
__metadata("design:type", Function),
|
|
31
|
+
__metadata("design:paramtypes", []),
|
|
32
|
+
__metadata("design:returntype", void 0)
|
|
33
|
+
], PoolStatusController.prototype, "getStatus", null);
|
|
34
|
+
exports.PoolStatusController = PoolStatusController = __decorate([
|
|
35
|
+
(0, common_1.Controller)('/status'),
|
|
36
|
+
__metadata("design:paramtypes", [browser_pool_service_1.BrowserPoolService])
|
|
37
|
+
], PoolStatusController);
|
|
38
|
+
//# sourceMappingURL=pool-status.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool-status.controller.js","sourceRoot":"","sources":["../../src/controllers/pool-status.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAiD;AACjD,2EAAuE;AAGhE,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAE/B,YAA6B,YAAgC;QAAhC,iBAAY,GAAZ,YAAY,CAAoB;IAAI,CAAC;IAGlE,SAAS;QACP,OAAO;YACL,gBAAgB,EAAE,IAAI,CAAC,YAAY,CAAC,gBAAgB;YACpD,gBAAgB,EAAE,IAAI,CAAC,YAAY,CAAC,0BAA0B;YAC9D,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,qBAAqB;SACtD,CAAC;IACJ,CAAC;CAEF,CAAA;AAbY,oDAAoB;AAK/B;IADC,IAAA,YAAG,GAAE;;;;qDAOL;+BAXU,oBAAoB;IADhC,IAAA,mBAAU,EAAC,SAAS,CAAC;qCAGuB,yCAAkB;GAFlD,oBAAoB,CAahC"}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@nestjs/core");
|
|
4
|
+
const app_module_1 = require("./app.module");
|
|
5
|
+
async function bootstrap() {
|
|
6
|
+
const app = await core_1.NestFactory.create(app_module_1.AppModule);
|
|
7
|
+
await app.listen(process.env.PORT || 9999);
|
|
8
|
+
}
|
|
9
|
+
bootstrap();
|
|
10
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,6CAAyC;AAEzC,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,CAAC;IAChD,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { BrowserInstance } from 'src/components/browser-instance.component';
|
|
3
|
+
import * as EventEmitter from 'events';
|
|
4
|
+
import { ModuleRef } from '@nestjs/core';
|
|
5
|
+
type PoolServiceEvents = {
|
|
6
|
+
browser_instance_created: [BrowserInstance];
|
|
7
|
+
};
|
|
8
|
+
export interface BrowserPoolStatus {
|
|
9
|
+
id: string;
|
|
10
|
+
started_at: string;
|
|
11
|
+
max_browser_instances: number;
|
|
12
|
+
tags: {
|
|
13
|
+
[key: string]: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare class BrowserPoolService extends EventEmitter<PoolServiceEvents> implements OnModuleInit {
|
|
17
|
+
#private;
|
|
18
|
+
private readonly module_ref;
|
|
19
|
+
private readonly logger;
|
|
20
|
+
readonly max_browser_instances: number;
|
|
21
|
+
constructor(module_ref: ModuleRef);
|
|
22
|
+
get status(): BrowserPoolStatus;
|
|
23
|
+
get id(): string;
|
|
24
|
+
get started_at(): string;
|
|
25
|
+
get tags(): {
|
|
26
|
+
[key: string]: string;
|
|
27
|
+
};
|
|
28
|
+
get sigterm_received(): boolean;
|
|
29
|
+
get nb_browser_instances_alive(): number;
|
|
30
|
+
get browser_instances(): BrowserInstance[];
|
|
31
|
+
onModuleInit(): Promise<void>;
|
|
32
|
+
getBrowserInstanceById(id: string): BrowserInstance | undefined;
|
|
33
|
+
createBrowserInstance(id?: string): BrowserInstance;
|
|
34
|
+
shutdown(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
12
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
13
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
14
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
15
|
+
};
|
|
16
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
17
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
18
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
19
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
20
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
21
|
+
};
|
|
22
|
+
var _BrowserPoolService_id, _BrowserPoolService_started_at, _BrowserPoolService_tags, _BrowserPoolService_browser_instances, _BrowserPoolService_sigterm_received;
|
|
23
|
+
var BrowserPoolService_1;
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.BrowserPoolService = void 0;
|
|
26
|
+
const common_1 = require("@nestjs/common");
|
|
27
|
+
const browser_instance_component_1 = require("../components/browser-instance.component");
|
|
28
|
+
const EventEmitter = require("events");
|
|
29
|
+
const core_1 = require("@nestjs/core");
|
|
30
|
+
let BrowserPoolService = BrowserPoolService_1 = class BrowserPoolService extends EventEmitter {
|
|
31
|
+
constructor(module_ref) {
|
|
32
|
+
super();
|
|
33
|
+
this.module_ref = module_ref;
|
|
34
|
+
this.logger = new common_1.Logger(BrowserPoolService_1.name);
|
|
35
|
+
_BrowserPoolService_id.set(this, crypto.randomUUID());
|
|
36
|
+
_BrowserPoolService_started_at.set(this, new Date().toISOString());
|
|
37
|
+
_BrowserPoolService_tags.set(this, {});
|
|
38
|
+
this.max_browser_instances = parseInt(process.env.MAX_BROWSER_INSTANCES);
|
|
39
|
+
_BrowserPoolService_browser_instances.set(this, new Map());
|
|
40
|
+
_BrowserPoolService_sigterm_received.set(this, false);
|
|
41
|
+
(process.env.TAGS || '').split(',').forEach(tag => {
|
|
42
|
+
const [key, value] = tag.split('=');
|
|
43
|
+
__classPrivateFieldGet(this, _BrowserPoolService_tags, "f")[key] = value;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
get status() {
|
|
47
|
+
return {
|
|
48
|
+
id: __classPrivateFieldGet(this, _BrowserPoolService_id, "f"),
|
|
49
|
+
started_at: __classPrivateFieldGet(this, _BrowserPoolService_started_at, "f"),
|
|
50
|
+
max_browser_instances: this.max_browser_instances,
|
|
51
|
+
tags: __classPrivateFieldGet(this, _BrowserPoolService_tags, "f")
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
get id() {
|
|
55
|
+
return __classPrivateFieldGet(this, _BrowserPoolService_id, "f");
|
|
56
|
+
}
|
|
57
|
+
get started_at() {
|
|
58
|
+
return __classPrivateFieldGet(this, _BrowserPoolService_started_at, "f");
|
|
59
|
+
}
|
|
60
|
+
get tags() {
|
|
61
|
+
return __classPrivateFieldGet(this, _BrowserPoolService_tags, "f");
|
|
62
|
+
}
|
|
63
|
+
get sigterm_received() {
|
|
64
|
+
return __classPrivateFieldGet(this, _BrowserPoolService_sigterm_received, "f");
|
|
65
|
+
}
|
|
66
|
+
get nb_browser_instances_alive() {
|
|
67
|
+
return __classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").size;
|
|
68
|
+
}
|
|
69
|
+
get browser_instances() {
|
|
70
|
+
return [...__classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").values()];
|
|
71
|
+
}
|
|
72
|
+
async onModuleInit() {
|
|
73
|
+
process.on('SIGTERM', () => {
|
|
74
|
+
this.logger.log('SIGTERM received');
|
|
75
|
+
this.shutdown();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
getBrowserInstanceById(id) {
|
|
79
|
+
return __classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").get(id);
|
|
80
|
+
}
|
|
81
|
+
createBrowserInstance(id = crypto.randomUUID()) {
|
|
82
|
+
if (this.sigterm_received) {
|
|
83
|
+
this.logger.log(`Can't create new browser instance. Sigterm has been received.`);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const browser_instance = new browser_instance_component_1.BrowserInstance(id, this.module_ref);
|
|
87
|
+
this.logger.log(`Created browser instance ${browser_instance.id}.`);
|
|
88
|
+
this.emit('browser_instance_created', browser_instance);
|
|
89
|
+
browser_instance.on('terminated', () => {
|
|
90
|
+
this.logger.log(`Browser instance ${browser_instance.id} terminated. Removing from pool.`);
|
|
91
|
+
__classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").delete(browser_instance.id);
|
|
92
|
+
});
|
|
93
|
+
__classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").set(browser_instance.id, browser_instance);
|
|
94
|
+
return browser_instance;
|
|
95
|
+
}
|
|
96
|
+
async shutdown() {
|
|
97
|
+
if (__classPrivateFieldGet(this, _BrowserPoolService_sigterm_received, "f")) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
__classPrivateFieldSet(this, _BrowserPoolService_sigterm_received, true, "f");
|
|
101
|
+
this.logger.log('Shutdown requested.');
|
|
102
|
+
for (const browser_instance of __classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").values()) {
|
|
103
|
+
if (browser_instance.in_use) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
await browser_instance.close();
|
|
107
|
+
}
|
|
108
|
+
setInterval(async () => {
|
|
109
|
+
if (__classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").size !== 0) {
|
|
110
|
+
this.logger.log(`Waiting for ${__classPrivateFieldGet(this, _BrowserPoolService_browser_instances, "f").size} browser instance(s) to close.`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.logger.log(`All browser instances are closed.`);
|
|
114
|
+
process.exit(0);
|
|
115
|
+
}, 200);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
exports.BrowserPoolService = BrowserPoolService;
|
|
119
|
+
_BrowserPoolService_id = new WeakMap();
|
|
120
|
+
_BrowserPoolService_started_at = new WeakMap();
|
|
121
|
+
_BrowserPoolService_tags = new WeakMap();
|
|
122
|
+
_BrowserPoolService_browser_instances = new WeakMap();
|
|
123
|
+
_BrowserPoolService_sigterm_received = new WeakMap();
|
|
124
|
+
exports.BrowserPoolService = BrowserPoolService = BrowserPoolService_1 = __decorate([
|
|
125
|
+
(0, common_1.Injectable)(),
|
|
126
|
+
__metadata("design:paramtypes", [core_1.ModuleRef])
|
|
127
|
+
], BrowserPoolService);
|
|
128
|
+
//# sourceMappingURL=browser-pool.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-pool.service.js","sourceRoot":"","sources":["../../src/services/browser-pool.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
14
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
15
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
16
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
17
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
18
|
+
};
|
|
19
|
+
var _TimezoneService_default_timezone;
|
|
20
|
+
var TimezoneService_1;
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.TimezoneService = void 0;
|
|
23
|
+
const common_1 = require("@nestjs/common");
|
|
24
|
+
const axios_1 = require("axios");
|
|
25
|
+
let TimezoneService = TimezoneService_1 = class TimezoneService {
|
|
26
|
+
constructor() {
|
|
27
|
+
this.logger = new common_1.Logger(TimezoneService_1.name);
|
|
28
|
+
_TimezoneService_default_timezone.set(this, void 0);
|
|
29
|
+
}
|
|
30
|
+
getDefaultTimezone() {
|
|
31
|
+
if (!__classPrivateFieldGet(this, _TimezoneService_default_timezone, "f")) {
|
|
32
|
+
__classPrivateFieldSet(this, _TimezoneService_default_timezone, new Promise(async (res) => {
|
|
33
|
+
res((await (await fetch('http://ip-api.com/json?fields=timezone')).json()).timezone);
|
|
34
|
+
}), "f");
|
|
35
|
+
}
|
|
36
|
+
return __classPrivateFieldGet(this, _TimezoneService_default_timezone, "f");
|
|
37
|
+
}
|
|
38
|
+
async getProxyTimezone(proxy_url) {
|
|
39
|
+
try {
|
|
40
|
+
const url = new URL(proxy_url);
|
|
41
|
+
const response = await axios_1.default.get('http://ip-api.com/json?fields=timezone', {
|
|
42
|
+
proxy: {
|
|
43
|
+
protocol: url.protocol,
|
|
44
|
+
host: url.hostname,
|
|
45
|
+
port: parseInt(url.port),
|
|
46
|
+
auth: {
|
|
47
|
+
username: url.username,
|
|
48
|
+
password: url.password,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return response.data.timezone;
|
|
53
|
+
}
|
|
54
|
+
catch (e) {
|
|
55
|
+
this.logger.error(`Error while getting timezone.`, e);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
exports.TimezoneService = TimezoneService;
|
|
60
|
+
_TimezoneService_default_timezone = new WeakMap();
|
|
61
|
+
exports.TimezoneService = TimezoneService = TimezoneService_1 = __decorate([
|
|
62
|
+
(0, common_1.Injectable)()
|
|
63
|
+
], TimezoneService);
|
|
64
|
+
//# sourceMappingURL=timezone.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timezone.service.js","sourceRoot":"","sources":["../../src/services/timezone.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,iCAA0B;AAGnB,IAAM,eAAe,uBAArB,MAAM,eAAe;IAArB;QAEc,WAAM,GAAG,IAAI,eAAM,CAAC,iBAAe,CAAC,IAAI,CAAC,CAAC;QAE3D,oDAAmC;IAiCvC,CAAC;IA/BG,kBAAkB;QACd,IAAI,CAAC,uBAAA,IAAI,yCAAkB,EAAE,CAAC;YAC1B,uBAAA,IAAI,qCAAqB,IAAI,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC/C,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;YACzF,CAAC,CAAC,MAAA,CAAC;QACP,CAAC;QAED,OAAO,uBAAA,IAAI,yCAAkB,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,SAAiB;QACpC,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;YAC/B,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,wCAAwC,EAAE;gBACvE,KAAK,EAAE;oBACH,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,IAAI,EAAE,GAAG,CAAC,QAAQ;oBAClB,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;oBACxB,IAAI,EAAE;wBACF,QAAQ,EAAE,GAAG,CAAC,QAAQ;wBACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ;qBACzB;iBACJ;aACJ,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;QAClC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC,CAAC,CAAC;QAC1D,CAAC;IACL,CAAC;CAEJ,CAAA;AArCY,0CAAe;;0BAAf,eAAe;IAD3B,IAAA,mBAAU,GAAE;GACA,eAAe,CAqC3B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
2
|
+
export declare abstract class UserDataService {
|
|
3
|
+
#private;
|
|
4
|
+
abstract downloadUserData(id: string, user_data_folder: string): Promise<void>;
|
|
5
|
+
abstract uploadUserData(id: string, user_data_folder: string): Promise<void>;
|
|
6
|
+
protected tarUserDataFolder(user_data_folder: string): Promise<string>;
|
|
7
|
+
protected untarUserDataFolder(tar_file: string, user_data_folder: string): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export declare class UserDataS3Service extends UserDataService {
|
|
10
|
+
private readonly s3_client;
|
|
11
|
+
private readonly logger;
|
|
12
|
+
constructor(s3_client: S3Client);
|
|
13
|
+
downloadUserData(id: string, user_data_folder: string): Promise<void>;
|
|
14
|
+
uploadUserData(id: string, user_data_folder: string): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
12
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
13
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
14
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
15
|
+
};
|
|
16
|
+
var _UserDataService_instances, _UserDataService_cleanUserDataFolder;
|
|
17
|
+
var UserDataS3Service_1;
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.UserDataS3Service = exports.UserDataService = void 0;
|
|
20
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
21
|
+
const common_1 = require("@nestjs/common");
|
|
22
|
+
const fs = require("fs");
|
|
23
|
+
const fsPromise = require("fs/promises");
|
|
24
|
+
const zlib = require("zlib");
|
|
25
|
+
const tar = require("tar");
|
|
26
|
+
const limit_stream_1 = require("../transforms/limit-stream");
|
|
27
|
+
class UserDataService {
|
|
28
|
+
constructor() {
|
|
29
|
+
_UserDataService_instances.add(this);
|
|
30
|
+
}
|
|
31
|
+
async tarUserDataFolder(user_data_folder) {
|
|
32
|
+
const tar_file = `${crypto.randomUUID()}.tar.gz`;
|
|
33
|
+
await __classPrivateFieldGet(this, _UserDataService_instances, "m", _UserDataService_cleanUserDataFolder).call(this, user_data_folder);
|
|
34
|
+
await tar.create({
|
|
35
|
+
gzip: true,
|
|
36
|
+
file: tar_file,
|
|
37
|
+
cwd: user_data_folder
|
|
38
|
+
}, ['.']);
|
|
39
|
+
return tar_file;
|
|
40
|
+
}
|
|
41
|
+
async untarUserDataFolder(tar_file, user_data_folder) {
|
|
42
|
+
await new Promise((res, rej) => {
|
|
43
|
+
fs.createReadStream(tar_file)
|
|
44
|
+
.pipe(zlib.createGunzip())
|
|
45
|
+
.pipe(new limit_stream_1.default(104857600))
|
|
46
|
+
.pipe(tar.extract({ cwd: user_data_folder }))
|
|
47
|
+
.on('finish', () => {
|
|
48
|
+
res(undefined);
|
|
49
|
+
})
|
|
50
|
+
.on('error', (err) => {
|
|
51
|
+
rej(err);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
await __classPrivateFieldGet(this, _UserDataService_instances, "m", _UserDataService_cleanUserDataFolder).call(this, user_data_folder);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.UserDataService = UserDataService;
|
|
58
|
+
_UserDataService_instances = new WeakSet(), _UserDataService_cleanUserDataFolder = async function _UserDataService_cleanUserDataFolder(user_data_folder) {
|
|
59
|
+
await Promise.allSettled([
|
|
60
|
+
fsPromise.rm(`${user_data_folder}/Default/Sessions`, { recursive: true, force: true }),
|
|
61
|
+
fsPromise.rm(`${user_data_folder}/SingletonLock`, { force: true }),
|
|
62
|
+
fsPromise.rm(`${user_data_folder}/SingletonCookie`, { force: true }),
|
|
63
|
+
fsPromise.rm(`${user_data_folder}/SingletonSocket`, { force: true }),
|
|
64
|
+
]);
|
|
65
|
+
};
|
|
66
|
+
let UserDataS3Service = UserDataS3Service_1 = class UserDataS3Service extends UserDataService {
|
|
67
|
+
constructor(s3_client) {
|
|
68
|
+
super();
|
|
69
|
+
this.s3_client = s3_client;
|
|
70
|
+
this.logger = new common_1.Logger(UserDataS3Service_1.name);
|
|
71
|
+
}
|
|
72
|
+
async downloadUserData(id, user_data_folder) {
|
|
73
|
+
try {
|
|
74
|
+
const tar_file = `/tmp/${crypto.randomUUID()}`;
|
|
75
|
+
const response = await this.s3_client.send(new client_s3_1.GetObjectCommand({
|
|
76
|
+
Bucket: process.env.S3_USER_DATA_BUCKET,
|
|
77
|
+
Key: id,
|
|
78
|
+
}));
|
|
79
|
+
await fsPromise.writeFile(tar_file, await response.Body.transformToByteArray());
|
|
80
|
+
await this.untarUserDataFolder(tar_file, user_data_folder);
|
|
81
|
+
await fsPromise.rm(tar_file);
|
|
82
|
+
this.logger.log(`Downloaded user data ${id} folder:${user_data_folder}`);
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
if (e.Code === 'NoSuchKey') {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
throw e;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async uploadUserData(id, user_data_folder) {
|
|
92
|
+
const tar_file = await this.tarUserDataFolder(user_data_folder);
|
|
93
|
+
await this.s3_client.send(new client_s3_1.PutObjectCommand({
|
|
94
|
+
Bucket: process.env.S3_USER_DATA_BUCKET,
|
|
95
|
+
Key: id,
|
|
96
|
+
Body: await fsPromise.readFile(tar_file)
|
|
97
|
+
}));
|
|
98
|
+
await fsPromise.rm(tar_file);
|
|
99
|
+
this.logger.log(`Uploaded user data ${id} folder:${user_data_folder}`);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
exports.UserDataS3Service = UserDataS3Service;
|
|
103
|
+
exports.UserDataS3Service = UserDataS3Service = UserDataS3Service_1 = __decorate([
|
|
104
|
+
(0, common_1.Injectable)(),
|
|
105
|
+
__metadata("design:paramtypes", [client_s3_1.S3Client])
|
|
106
|
+
], UserDataS3Service);
|
|
107
|
+
//# sourceMappingURL=user-data.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-data.service.js","sourceRoot":"","sources":["../../src/services/user-data.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Transform, TransformCallback, TransformOptions } from 'stream';
|
|
2
|
+
export default class LimitStream extends Transform {
|
|
3
|
+
private readonly byte_limit;
|
|
4
|
+
private bytes_processed;
|
|
5
|
+
constructor(byte_limit: number, options?: TransformOptions);
|
|
6
|
+
_transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void;
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const stream_1 = require("stream");
|
|
4
|
+
class LimitStream extends stream_1.Transform {
|
|
5
|
+
constructor(byte_limit, options) {
|
|
6
|
+
super(options);
|
|
7
|
+
this.byte_limit = byte_limit;
|
|
8
|
+
this.bytes_processed = 0;
|
|
9
|
+
}
|
|
10
|
+
_transform(chunk, encoding, callback) {
|
|
11
|
+
this.bytes_processed += chunk.length;
|
|
12
|
+
if (this.bytes_processed > this.byte_limit) {
|
|
13
|
+
const error = new Error(`Decompression limit exceeded. Max size: ${this.byte_limit} bytes`);
|
|
14
|
+
this.destroy(error);
|
|
15
|
+
return callback(error);
|
|
16
|
+
}
|
|
17
|
+
this.push(chunk);
|
|
18
|
+
callback();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.default = LimitStream;
|
|
22
|
+
//# sourceMappingURL=limit-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limit-stream.js","sourceRoot":"","sources":["../../src/transforms/limit-stream.ts"],"names":[],"mappings":";;AAAA,mCAAwE;AAMxE,MAAqB,WAAY,SAAQ,kBAAS;IAI9C,YACqB,UAAkB,EACnC,OAA0B;QAE1B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHE,eAAU,GAAV,UAAU,CAAQ;QAH/B,oBAAe,GAAG,CAAC,CAAC;IAO5B,CAAC;IAED,UAAU,CAAC,KAAU,EAAE,QAAwB,EAAE,QAA2B;QACxE,IAAI,CAAC,eAAe,IAAI,KAAK,CAAC,MAAM,CAAC;QAErC,IAAI,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,UAAU,QAAQ,CAAC,CAAC;YAC5F,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,QAAQ,EAAE,CAAC;IACf,CAAC;CACJ;AAvBD,8BAuBC"}
|