Switch to Typescript
This commit is contained in:
parent
34cb00139f
commit
535535efd3
37
.eslintrc.js
Normal file
37
.eslintrc.js
Normal file
@ -0,0 +1,37 @@
|
||||
module.exports = {
|
||||
env: { node: true },
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint", "prettier"],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"plugin:prettier/recommended",
|
||||
],
|
||||
ignorePatterns: [".eslintrc.js", "src/**/*.test.ts", "@types/*"],
|
||||
parserOptions: {
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
modules: true,
|
||||
},
|
||||
project: ["./tsconfig.json"],
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/require-await": 0,
|
||||
"no-await-in-loop": 2,
|
||||
},
|
||||
settings: { jsdoc: { mode: "typescript" } },
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.subtest.ts", "*.test.ts"],
|
||||
rules: {
|
||||
"@typescript-eslint/no-unsafe-member-access": 0,
|
||||
"prefer-const": 0,
|
||||
"@typescript-eslint/no-unsafe-call": 0,
|
||||
"@typescript-eslint/no-unsafe-return": 0,
|
||||
"@typescript-eslint/no-unsafe-assignment": 0,
|
||||
"no-await-in-loop": 1, // sometimes it's easier to debug when requests run sequentially
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,6 @@
|
||||
!@types
|
||||
/node_modules/
|
||||
/static/
|
||||
/.log/
|
||||
/yarn-error.log
|
||||
/lib/
|
||||
|
23
@types/src/container-pool.d.ts
vendored
Normal file
23
@types/src/container-pool.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/// <reference types="node" />
|
||||
import { ChildProcessWithoutNullStreams } from "child_process";
|
||||
export declare class Container {
|
||||
callbacks: Array<() => void>;
|
||||
ready: boolean;
|
||||
id: string;
|
||||
output: "";
|
||||
bg_process: ChildProcessWithoutNullStreams;
|
||||
constructor();
|
||||
signalReady(): void;
|
||||
onReady(callback: () => void): void;
|
||||
waitReady(): Promise<void>;
|
||||
close(): void;
|
||||
closeSync(): void;
|
||||
}
|
||||
declare const _default: {
|
||||
pool: Container[];
|
||||
concurrency: number;
|
||||
generateContainer(): void;
|
||||
getContainer(): Container;
|
||||
clear(): void;
|
||||
};
|
||||
export default _default;
|
2
@types/src/docker-args.d.ts
vendored
Normal file
2
@types/src/docker-args.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export const DOCKER_ARGS: string[];
|
||||
export const IMAGE_NAME: "headless-fox";
|
1
@types/src/index.d.ts
vendored
Normal file
1
@types/src/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export {};
|
5
@types/src/memory.d.ts
vendored
Normal file
5
@types/src/memory.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import queue from "queue";
|
||||
import ScreenshotRequest from "./request";
|
||||
declare const q: queue;
|
||||
declare const requests: Record<string, ScreenshotRequest | undefined>;
|
||||
export { requests, q };
|
35
@types/src/request.d.ts
vendored
Normal file
35
@types/src/request.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/// <reference types="node" />
|
||||
import { ChildProcessWithoutNullStreams } from "child_process";
|
||||
export default class ScreenshotRequest {
|
||||
url: string;
|
||||
domains: string[];
|
||||
id: string;
|
||||
status: string;
|
||||
output: string;
|
||||
images: Record<string, unknown>[];
|
||||
request_time: number;
|
||||
started_time: number | null;
|
||||
finished_time: number | null;
|
||||
processing_took: number | null;
|
||||
waiting_took: number | null;
|
||||
process: ChildProcessWithoutNullStreams;
|
||||
constructor(url: string, domains: string[]);
|
||||
getJobsAhead(): number;
|
||||
getJSON(): Promise<{
|
||||
url: string;
|
||||
domains: string[];
|
||||
jobs_ahead: number;
|
||||
id: string;
|
||||
status: string;
|
||||
output: string;
|
||||
images: Record<string, unknown>[];
|
||||
request_time: number;
|
||||
started_time: number | null;
|
||||
finished_time: number | null;
|
||||
processing_took: number | null;
|
||||
waiting_took: number | null;
|
||||
elapsed_time_s: number;
|
||||
}>;
|
||||
setFinished(): void;
|
||||
exec(): Promise<void>;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
const queue = require("queue");
|
||||
const { concurrency } = require("./config.json");
|
||||
const q = queue({ concurrency, autostart: true, results: [] });
|
||||
const requests = {};
|
||||
|
||||
module.exports = { q, requests };
|
3474
package-lock.json
generated
3474
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@ -2,10 +2,12 @@
|
||||
"name": "screenshot-service",
|
||||
"version": "1.0.0",
|
||||
"description": "## Dependencies",
|
||||
"main": "index.js",
|
||||
"main": "lib/src/index.js",
|
||||
"scripts": {
|
||||
"install-daemon": "cp screenshot-service.service /etc/systemd/system/ && systemctl start screenshot-service && systemctl enable screenshot-service",
|
||||
"start": "docker image build -t headless-fox Docker && BASE_URL=http://localhost:3000 node ."
|
||||
"start": "npm run build && docker image build -t headless-fox Docker && BASE_URL=http://localhost:3000 node .",
|
||||
"build": "tsc",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -15,6 +17,8 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@koa/router": "^10.1.1",
|
||||
"@sealcode/ts-predicates": "^0.2.2",
|
||||
"@types/node": "^18.0.0",
|
||||
"amqplib": "^0.8.0",
|
||||
"koa": "^2.13.4",
|
||||
"koa-mount": "^4.0.0",
|
||||
@ -22,5 +26,21 @@
|
||||
"qs": "^6.10.3",
|
||||
"queue": "^6.0.2",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/koa": "^2.13.4",
|
||||
"@types/koa__router": "^8.0.11",
|
||||
"@types/koa-mount": "^4.0.1",
|
||||
"@types/koa-static": "^4.0.2",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "^4.29.3",
|
||||
"@typescript-eslint/parser": "^4.29.3",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^3.4.1",
|
||||
"eslint-plugin-with-tsc-error": "^0.0.7",
|
||||
"prettier": "^2.3.2",
|
||||
"source-map-support": "^0.5.19",
|
||||
"typescript": "^4.3.5"
|
||||
}
|
||||
}
|
||||
|
119
request.js
119
request.js
@ -1,119 +0,0 @@
|
||||
const { q, requests } = require("./memory");
|
||||
|
||||
const DOCKER_ARGS = require("./docker-args");
|
||||
const { v4: uuid } = require("uuid");
|
||||
const { spawn } = require("child_process");
|
||||
const containerPool = require("./container-pool");
|
||||
|
||||
let queue_order = [];
|
||||
|
||||
module.exports = class ScreenshotRequest {
|
||||
constructor(url, domains) {
|
||||
this.url = url;
|
||||
this.domains = domains;
|
||||
this.id = uuid();
|
||||
this.status = "waiting";
|
||||
this.output = "";
|
||||
this.images = [];
|
||||
this.request_time = Date.now();
|
||||
this.started_time = null;
|
||||
this.finished_time = null;
|
||||
this.processing_took = null;
|
||||
this.waiting_took = null;
|
||||
q.push(async () => {
|
||||
return this.exec();
|
||||
});
|
||||
requests[this.id] = this;
|
||||
queue_order.push(this);
|
||||
}
|
||||
|
||||
getJobsAhead() {
|
||||
if (this.status != "waiting") {
|
||||
return 0;
|
||||
}
|
||||
let count = 0;
|
||||
for (const request of queue_order) {
|
||||
if (request == this) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
async getJSON() {
|
||||
return {
|
||||
url: this.url,
|
||||
domains: this.domains,
|
||||
jobs_ahead: this.getJobsAhead(),
|
||||
id: this.id,
|
||||
status: this.status,
|
||||
output: this.output,
|
||||
images: this.images,
|
||||
request_time: this.request_time,
|
||||
started_time: this.started_time,
|
||||
finished_time: this.finished_time,
|
||||
processing_took: this.processing_took,
|
||||
waiting_took: this.waiting_took,
|
||||
elapsed_time_s: Math.round(
|
||||
((this.status === "finished" ? this.finished_time : Date.now()) -
|
||||
this.request_time) /
|
||||
1000
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
setFinished() {
|
||||
this.status = "finished";
|
||||
this.finished_time = Date.now();
|
||||
this.processing_took = this.finished_time - this.started_time;
|
||||
this.waiting_took = this.started_time - this.request_time;
|
||||
}
|
||||
|
||||
async exec() {
|
||||
this.started_time = Date.now();
|
||||
return new Promise(async (resolve, reject) => {
|
||||
this.status = "running";
|
||||
const container = containerPool.getContainer();
|
||||
await container.waitReady();
|
||||
this.process = spawn(
|
||||
"docker",
|
||||
[
|
||||
"exec",
|
||||
container.id,
|
||||
"/opt/run-analysis.sh",
|
||||
JSON.stringify({
|
||||
url: this.url,
|
||||
third_party_domains: this.domains,
|
||||
}),
|
||||
this.id,
|
||||
],
|
||||
{ cwd: process.cwd() }
|
||||
);
|
||||
this.process.on("close", (exitCode) => {
|
||||
this.setFinished();
|
||||
container.close();
|
||||
queue_order = queue_order.filter((request) => request != this);
|
||||
if (exitCode === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
this.process.stdout.on("data", (d) => {
|
||||
try {
|
||||
const parsed = JSON.parse(d.toString());
|
||||
if (parsed.new_file) {
|
||||
this.images.push(parsed.new_file);
|
||||
}
|
||||
} catch (e) {}
|
||||
this.output += d.toString();
|
||||
/* console.log("DATA!", d.toString()); */
|
||||
});
|
||||
this.process.stderr.on("data", (d) => {
|
||||
this.output += d.toString();
|
||||
/* console.log("STDERR!", d.toString()); */
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
@ -1,11 +1,19 @@
|
||||
const { spawn, spawnSync } = require("child_process");
|
||||
const { IMAGE_NAME } = require("./docker-args");
|
||||
const { concurrency } = require("./config.json");
|
||||
import { hasShape, predicates, is } from "@sealcode/ts-predicates";
|
||||
import {
|
||||
ChildProcessWithoutNullStreams,
|
||||
spawn,
|
||||
spawnSync,
|
||||
} from "child_process";
|
||||
import { concurrency } from "../config.json";
|
||||
import { IMAGE_NAME } from "./docker-args";
|
||||
|
||||
class Container {
|
||||
export class Container {
|
||||
callbacks: Array<() => void> = [];
|
||||
ready = false;
|
||||
id: string;
|
||||
output: "";
|
||||
bg_process: ChildProcessWithoutNullStreams;
|
||||
constructor() {
|
||||
this.callbacks = [];
|
||||
this.ready = false;
|
||||
this.id = spawnSync(
|
||||
"docker",
|
||||
["run", "-d", "-v", `${process.cwd()}/static:/opt/static`, IMAGE_NAME],
|
||||
@ -15,51 +23,56 @@ class Container {
|
||||
)
|
||||
.stdout.toString()
|
||||
.replace("\n", "");
|
||||
this.output = "";
|
||||
this.bg_process = spawn("docker", ["logs", "-f", this.id]);
|
||||
this.bg_process.stdout.on("data", (d) => {
|
||||
this.bg_process.stdout.on("data", (d: Buffer) => {
|
||||
try {
|
||||
const parsed = JSON.parse(d.toString());
|
||||
if (parsed.code == "ready") {
|
||||
const parsed = JSON.parse(d.toString()) as unknown;
|
||||
if (
|
||||
is(parsed, predicates.object) &&
|
||||
hasShape({ code: predicates.string }, parsed) &&
|
||||
parsed.code == "ready"
|
||||
) {
|
||||
this.ready = true;
|
||||
this.signalReady();
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
// noop
|
||||
}
|
||||
this.output += d.toString();
|
||||
});
|
||||
}
|
||||
|
||||
signalReady() {
|
||||
this.callbacks.forEach((callback) => callback(this));
|
||||
signalReady(): void {
|
||||
this.callbacks.forEach((callback) => callback());
|
||||
}
|
||||
|
||||
onReady(callback) {
|
||||
onReady(callback: () => void): void {
|
||||
this.ready ? callback() : this.callbacks.push(callback);
|
||||
}
|
||||
|
||||
async waitReady() {
|
||||
async waitReady(): Promise<void> {
|
||||
if (this.ready) {
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
this.onReady(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
close() {
|
||||
close(): void {
|
||||
spawn("docker", ["rm", "-f", this.id]);
|
||||
}
|
||||
|
||||
closeSync() {
|
||||
closeSync(): void {
|
||||
spawnSync("docker", ["rm", "-f", this.id]);
|
||||
console.log("doker rm done", this.id);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new (class ContainerPool {
|
||||
constructor(concurrency) {
|
||||
export default new (class ContainerPool {
|
||||
pool: Container[] = [];
|
||||
constructor(public concurrency: number) {
|
||||
this.concurrency = concurrency;
|
||||
this.pool = [];
|
||||
for (let i = 1; i <= this.concurrency; i++) {
|
||||
this.generateContainer();
|
||||
}
|
||||
@ -79,6 +92,9 @@ module.exports = new (class ContainerPool {
|
||||
throw new Error("pool is empty, try again!");
|
||||
}
|
||||
const container = this.pool.shift(); // get and remove from pool the oldest container
|
||||
if (!container) {
|
||||
throw new Error("Pool was somehow empty!");
|
||||
}
|
||||
this.generateContainer();
|
||||
return container;
|
||||
}
|
@ -1,33 +1,34 @@
|
||||
var serve = require("koa-static");
|
||||
const { v4: uuid } = require("uuid");
|
||||
const Koa = require("koa");
|
||||
const Router = require("@koa/router");
|
||||
const mount = require("koa-mount");
|
||||
const qs = require("qs");
|
||||
const { Readable } = require("stream");
|
||||
const { spawn } = require("child_process");
|
||||
const { requests } = require("./memory");
|
||||
const ScreenshotRequest = require("./request");
|
||||
const { DOCKER_ARGS } = require("./docker-args");
|
||||
import Router from "@koa/router";
|
||||
import { hasShape, predicates } from "@sealcode/ts-predicates";
|
||||
import { spawn } from "child_process";
|
||||
import Koa from "koa";
|
||||
import mount from "koa-mount";
|
||||
import serve from "koa-static";
|
||||
import qs from "qs";
|
||||
import { Readable } from "stream";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { DOCKER_ARGS } from "./docker-args";
|
||||
import { requests } from "./memory";
|
||||
import ScreenshotRequest from "./request";
|
||||
|
||||
const router = new Router();
|
||||
|
||||
// response
|
||||
const app = new Koa();
|
||||
const static = new Koa();
|
||||
static.use(serve("./static"));
|
||||
const Static = new Koa();
|
||||
Static.use(serve("./static"));
|
||||
|
||||
app.use(mount("/static", static));
|
||||
app.use(mount("/static", Static));
|
||||
|
||||
function attach(docker_id, output_stream) {
|
||||
function attach(docker_id: string, output_stream: Readable) {
|
||||
// to prevent browser timeout
|
||||
const interval = setInterval(() => output_stream.push("<span></span>"), 500);
|
||||
const task = spawn("docker", ["logs", "-f", docker_id]);
|
||||
task.stdout.on("data", (d) => {
|
||||
task.stdout.on("data", (d: Buffer) => {
|
||||
output_stream.push(d);
|
||||
console.log("DATA!", d.toString());
|
||||
});
|
||||
task.stderr.on("data", (d) => {
|
||||
task.stderr.on("data", (d: Buffer) => {
|
||||
/* output_stream.push(d); */
|
||||
console.log("STDERR!", d.toString());
|
||||
});
|
||||
@ -91,21 +92,28 @@ router.get("/", async (ctx) => {
|
||||
});
|
||||
|
||||
router.get("/preview", async (ctx) => {
|
||||
const s = new Readable({ read() {} });
|
||||
const response = new Readable({
|
||||
read() {
|
||||
/*noop */
|
||||
},
|
||||
});
|
||||
// stream data
|
||||
ctx.response.set("content-type", "txt/html");
|
||||
ctx.type = "html"; // <-- THIS is the important step!
|
||||
ctx.body = s;
|
||||
ctx.body.push("<!doctype html>");
|
||||
ctx.body = response;
|
||||
response.push("<!doctype html>");
|
||||
const id = uuid();
|
||||
ctx.body.push(
|
||||
response.push(
|
||||
`<img id="preview" width="1080" height="608" src="/static/${id}/preview.png?id=0"/><br/>`
|
||||
);
|
||||
ctx.body.push(/* HTML */ `<script>
|
||||
response.push(/* HTML */ `<script>
|
||||
window.interval = setInterval(() => (preview.src = preview.src + "0"), 500);
|
||||
</script>`);
|
||||
const params = qs.parse(ctx.querystring);
|
||||
s.push(`Got request to screenshot ${params.url}<pre>`);
|
||||
if (!hasShape({ url: predicates.string }, params)) {
|
||||
throw new Error("MISSING URL PARAM");
|
||||
}
|
||||
response.push(`Got request to screenshot ${params.url}<pre>`);
|
||||
let docker_id = "";
|
||||
if (!params.url) {
|
||||
ctx.body = "specify url!";
|
||||
@ -120,25 +128,25 @@ router.get("/preview", async (ctx) => {
|
||||
],
|
||||
{ cwd: process.cwd() }
|
||||
);
|
||||
starter.stdout.on("data", (data) => {
|
||||
starter.stdout.on("data", (data: Buffer) => {
|
||||
docker_id += data.toString().replace(/\n/g, "");
|
||||
});
|
||||
|
||||
starter.on("close", () => {
|
||||
ctx.body.push("spawned " + docker_id);
|
||||
response.push("spawned " + docker_id);
|
||||
attach(docker_id, ctx.body);
|
||||
});
|
||||
});
|
||||
|
||||
router.post("/api/requests", async (ctx) => {
|
||||
const params = qs.parse(ctx.querystring);
|
||||
if (!params.url) {
|
||||
if (!hasShape({ url: predicates.string }, params)) {
|
||||
ctx.body = "Specify url";
|
||||
ctx.status = 422;
|
||||
return;
|
||||
}
|
||||
if (!params.domains) {
|
||||
ctx.body = "Specify domains";
|
||||
if (!hasShape({ domains: predicates.array(predicates.string) }, params)) {
|
||||
ctx.body = "Specify domains as an array of strings";
|
||||
ctx.status = 422;
|
||||
return;
|
||||
}
|
7
src/memory.ts
Normal file
7
src/memory.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import queue from "queue";
|
||||
import { concurrency } from "../config.json";
|
||||
import ScreenshotRequest from "./request";
|
||||
const q = queue({ concurrency, autostart: true, results: [] });
|
||||
const requests: Record<string, ScreenshotRequest | undefined> = {};
|
||||
|
||||
export { requests, q };
|
139
src/request.ts
Normal file
139
src/request.ts
Normal file
@ -0,0 +1,139 @@
|
||||
import { is, predicates } from "@sealcode/ts-predicates";
|
||||
import { ChildProcessWithoutNullStreams, spawn } from "child_process";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import containerPool from "./container-pool";
|
||||
import { q, requests } from "./memory";
|
||||
|
||||
let queue_order: ScreenshotRequest[] = [];
|
||||
|
||||
export default class ScreenshotRequest {
|
||||
public id = uuid();
|
||||
public status = "waiting";
|
||||
public output = "";
|
||||
public images: Record<string, unknown>[] = [];
|
||||
public request_time: number = Date.now();
|
||||
public started_time: number | null = null;
|
||||
public finished_time: number | null = null;
|
||||
public processing_took: number | null = null;
|
||||
public waiting_took: number | null = null;
|
||||
public process: ChildProcessWithoutNullStreams;
|
||||
|
||||
constructor(public url: string, public domains: string[]) {
|
||||
q.push(async () => {
|
||||
return this.exec();
|
||||
});
|
||||
requests[this.id] = this;
|
||||
queue_order.push(this);
|
||||
}
|
||||
|
||||
getJobsAhead(): number {
|
||||
if (this.status != "waiting") {
|
||||
return 0;
|
||||
}
|
||||
let count = 0;
|
||||
for (const request of queue_order) {
|
||||
if (request == this) {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
async getJSON(): Promise<{
|
||||
url: string;
|
||||
domains: string[];
|
||||
jobs_ahead: number;
|
||||
id: string;
|
||||
status: string;
|
||||
output: string;
|
||||
images: Record<string, unknown>[];
|
||||
request_time: number;
|
||||
started_time: number | null;
|
||||
finished_time: number | null;
|
||||
processing_took: number | null;
|
||||
waiting_took: number | null;
|
||||
elapsed_time_s: number;
|
||||
}> {
|
||||
return {
|
||||
url: this.url,
|
||||
domains: this.domains,
|
||||
jobs_ahead: this.getJobsAhead(),
|
||||
id: this.id,
|
||||
status: this.status,
|
||||
output: this.output,
|
||||
images: this.images,
|
||||
request_time: this.request_time,
|
||||
started_time: this.started_time,
|
||||
finished_time: this.finished_time,
|
||||
processing_took: this.processing_took,
|
||||
waiting_took: this.waiting_took,
|
||||
elapsed_time_s: Math.round(
|
||||
((this.status === "finished" ? this.finished_time || -1 : Date.now()) -
|
||||
this.request_time) /
|
||||
1000
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
setFinished(): void {
|
||||
this.status = "finished";
|
||||
this.finished_time = Date.now();
|
||||
if (this.started_time) {
|
||||
this.processing_took = this.finished_time - this.started_time;
|
||||
this.waiting_took = this.started_time - this.request_time;
|
||||
}
|
||||
}
|
||||
|
||||
async exec(): Promise<void> {
|
||||
this.started_time = Date.now();
|
||||
this.status = "running";
|
||||
const container = containerPool.getContainer();
|
||||
await container.waitReady();
|
||||
return new Promise((resolve, reject) => {
|
||||
this.process = spawn(
|
||||
"docker",
|
||||
[
|
||||
"exec",
|
||||
container.id,
|
||||
"/opt/run-analysis.sh",
|
||||
JSON.stringify({
|
||||
url: this.url,
|
||||
third_party_domains: this.domains,
|
||||
}),
|
||||
this.id,
|
||||
],
|
||||
{ cwd: process.cwd() }
|
||||
);
|
||||
this.process.on("close", (exitCode) => {
|
||||
this.setFinished();
|
||||
container.close();
|
||||
queue_order = queue_order.filter((request) => request != this);
|
||||
if (exitCode === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
this.process.stdout.on("data", (d: Buffer) => {
|
||||
try {
|
||||
const parsed = JSON.parse(d.toString()) as unknown;
|
||||
if (
|
||||
is(parsed, predicates.object) &&
|
||||
is(parsed.new_file, predicates.object)
|
||||
) {
|
||||
this.images.push(parsed.new_file);
|
||||
}
|
||||
} catch (e) {
|
||||
//noop
|
||||
}
|
||||
this.output += d.toString();
|
||||
/* console.log("DATA!", d.toString()); */
|
||||
});
|
||||
this.process.stderr.on("data", (d: Buffer) => {
|
||||
this.output += d.toString();
|
||||
/* console.log("STDERR!", d.toString()); */
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
28
tsconfig.json
Normal file
28
tsconfig.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"strictNullChecks": true,
|
||||
"target": "ES6",
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"ES6",
|
||||
"ESNext"
|
||||
],
|
||||
"outDir": "lib",
|
||||
"checkJs": true,
|
||||
"allowJs": true,
|
||||
"declarationDir": "@types",
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"src/**/*.test.ts"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user