testeranto 0.219.14 → 0.219.15
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/package.json +1 -1
- package/src/testeranto.ts +1 -1
- package/dist/common/allTestsUtils.js +0 -17
- package/dist/common/package.json +0 -3
- package/dist/common/scripts/build-example.js +0 -105
- package/dist/common/src/Init.js +0 -38
- package/dist/common/src/Types.js +0 -63
- package/dist/common/src/esbuildConfigs/consoleDetectorPlugin.js +0 -38
- package/dist/common/src/esbuildConfigs/eslint-formatter-testeranto.js +0 -21
- package/dist/common/src/esbuildConfigs/featuresPlugin.js +0 -39
- package/dist/common/src/esbuildConfigs/index.js +0 -22
- package/dist/common/src/esbuildConfigs/inputFilesPlugin.js +0 -30
- package/dist/common/src/esbuildConfigs/nativeImportDetectorPlugin.js +0 -24
- package/dist/common/src/esbuildConfigs/rebuildPlugin.js +0 -19
- package/dist/common/src/init-docs.js +0 -9
- package/dist/common/src/lib/tiposkripto/BaseGiven.js +0 -96
- package/dist/common/src/lib/tiposkripto/BaseSuite.js +0 -134
- package/dist/common/src/lib/tiposkripto/BaseThen.js +0 -65
- package/dist/common/src/lib/tiposkripto/BaseTiposkripto.js +0 -193
- package/dist/common/src/lib/tiposkripto/BaseWhen.js +0 -46
- package/dist/common/src/lib/tiposkripto/CoreTypes.js +0 -2
- package/dist/common/src/lib/tiposkripto/Node.js +0 -40
- package/dist/common/src/lib/tiposkripto/Tiposkripto.js +0 -49
- package/dist/common/src/lib/tiposkripto/Types.js +0 -2
- package/dist/common/src/lib/tiposkripto/Web.js +0 -70
- package/dist/common/src/lib/tiposkripto/abstractBase.test/MockGiven.js +0 -22
- package/dist/common/src/lib/tiposkripto/abstractBase.test/MockThen.js +0 -16
- package/dist/common/src/lib/tiposkripto/abstractBase.test/MockWhen.js +0 -18
- package/dist/common/src/lib/tiposkripto/abstractBase.test/adapter.js +0 -24
- package/dist/common/src/lib/tiposkripto/abstractBase.test/implementation.js +0 -38
- package/dist/common/src/lib/tiposkripto/abstractBase.test/index.js +0 -17
- package/dist/common/src/lib/tiposkripto/abstractBase.test/specification.js +0 -19
- package/dist/common/src/lib/tiposkripto/abstractBase.test/types.js +0 -2
- package/dist/common/src/lib/tiposkripto/index.js +0 -29
- package/dist/common/src/runtimes.js +0 -4
- package/dist/common/src/server/aider/configParser.js +0 -124
- package/dist/common/src/server/aider/docker.js +0 -30
- package/dist/common/src/server/getRunnables.js +0 -36
- package/dist/common/src/server/htmlTemplate.js +0 -44
- package/dist/common/src/server/nodeVersion.js +0 -5
- package/dist/common/src/server/runtimes/common.js +0 -136
- package/dist/common/src/server/runtimes/golang/docker.js +0 -62
- package/dist/common/src/server/runtimes/java/docker.js +0 -46
- package/dist/common/src/server/runtimes/node/docker.js +0 -42
- package/dist/common/src/server/runtimes/node/esbuild.js +0 -40
- package/dist/common/src/server/runtimes/node/node.js +0 -75
- package/dist/common/src/server/runtimes/python/docker.js +0 -31
- package/dist/common/src/server/runtimes/ruby/docker.js +0 -34
- package/dist/common/src/server/runtimes/rust/docker.js +0 -35
- package/dist/common/src/server/runtimes/web/docker.js +0 -42
- package/dist/common/src/server/runtimes/web/esbuild.js +0 -29
- package/dist/common/src/server/runtimes/web/hoist.js +0 -16
- package/dist/common/src/server/runtimes/web/web.js +0 -157
- package/dist/common/src/server/serverClasees/Server.js +0 -47
- package/dist/common/src/server/serverClasees/Server_Base.js +0 -18
- package/dist/common/src/server/serverClasees/Server_Docker.js +0 -904
- package/dist/common/src/server/serverClasees/Server_FS.js +0 -119
- package/dist/common/src/server/serverClasees/Server_HTTP.js +0 -189
- package/dist/common/src/server/serverClasees/Server_WS.js +0 -262
- package/dist/common/src/server/serverManagers/DockerManager.js +0 -28
- package/dist/common/src/server/serverManagers/HttpManager.js +0 -114
- package/dist/common/src/server/serverManagers/WsManager.js +0 -230
- package/dist/common/src/server/serverManagers/fs.js +0 -32
- package/dist/common/src/server/serverManagers/tcp.js +0 -51
- package/dist/common/src/server/types.js +0 -2
- package/dist/common/src/testeranto.js +0 -75
- package/dist/common/src/vscode/TerminalManager.js +0 -129
- package/dist/common/src/vscode/TestTreeItem.js +0 -77
- package/dist/common/src/vscode/extension.js +0 -185
- package/dist/common/src/vscode/providers/FeaturesTreeDataProvider.js +0 -445
- package/dist/common/src/vscode/providers/FileTreeDataProvider.js +0 -190
- package/dist/common/src/vscode/providers/ProcessesTreeDataProvider.js +0 -270
- package/dist/common/src/vscode/providers/ResultsTreeDataProvider.js +0 -87
- package/dist/common/src/vscode/providers/TestTreeDataProvider.js +0 -309
- package/dist/common/src/vscode/types.js +0 -9
- package/dist/common/testeranto/runtimes/node/node.js +0 -7
- package/dist/common/testeranto/runtimes/web/web.js +0 -6
- package/dist/common/testeranto/testeranto.js +0 -70
- package/dist/common/tsconfig.common.tsbuildinfo +0 -1
- package/dist/module/allTestsUtils.js +0 -13
- package/dist/module/package.json +0 -3
- package/dist/module/scripts/build-example.js +0 -100
- package/dist/module/src/Init.js +0 -33
- package/dist/module/src/Types.js +0 -62
- package/dist/module/src/esbuildConfigs/consoleDetectorPlugin.js +0 -32
- package/dist/module/src/esbuildConfigs/eslint-formatter-testeranto.js +0 -18
- package/dist/module/src/esbuildConfigs/featuresPlugin.js +0 -34
- package/dist/module/src/esbuildConfigs/index.js +0 -20
- package/dist/module/src/esbuildConfigs/inputFilesPlugin.js +0 -25
- package/dist/module/src/esbuildConfigs/nativeImportDetectorPlugin.js +0 -21
- package/dist/module/src/esbuildConfigs/rebuildPlugin.js +0 -14
- package/dist/module/src/init-docs.js +0 -4
- package/dist/module/src/lib/tiposkripto/BaseGiven.js +0 -92
- package/dist/module/src/lib/tiposkripto/BaseSuite.js +0 -130
- package/dist/module/src/lib/tiposkripto/BaseThen.js +0 -61
- package/dist/module/src/lib/tiposkripto/BaseTiposkripto.js +0 -190
- package/dist/module/src/lib/tiposkripto/BaseWhen.js +0 -42
- package/dist/module/src/lib/tiposkripto/CoreTypes.js +0 -1
- package/dist/module/src/lib/tiposkripto/Node.js +0 -33
- package/dist/module/src/lib/tiposkripto/Tiposkripto.js +0 -14
- package/dist/module/src/lib/tiposkripto/Types.js +0 -1
- package/dist/module/src/lib/tiposkripto/Web.js +0 -63
- package/dist/module/src/lib/tiposkripto/abstractBase.test/MockGiven.js +0 -18
- package/dist/module/src/lib/tiposkripto/abstractBase.test/MockThen.js +0 -12
- package/dist/module/src/lib/tiposkripto/abstractBase.test/MockWhen.js +0 -14
- package/dist/module/src/lib/tiposkripto/abstractBase.test/adapter.js +0 -21
- package/dist/module/src/lib/tiposkripto/abstractBase.test/implementation.js +0 -35
- package/dist/module/src/lib/tiposkripto/abstractBase.test/index.js +0 -12
- package/dist/module/src/lib/tiposkripto/abstractBase.test/specification.js +0 -15
- package/dist/module/src/lib/tiposkripto/abstractBase.test/types.js +0 -1
- package/dist/module/src/lib/tiposkripto/index.js +0 -24
- package/dist/module/src/runtimes.js +0 -1
- package/dist/module/src/server/aider/configParser.js +0 -116
- package/dist/module/src/server/aider/docker.js +0 -28
- package/dist/module/src/server/getRunnables.js +0 -29
- package/dist/module/src/server/htmlTemplate.js +0 -40
- package/dist/module/src/server/nodeVersion.js +0 -2
- package/dist/module/src/server/runtimes/common.js +0 -127
- package/dist/module/src/server/runtimes/golang/docker.js +0 -55
- package/dist/module/src/server/runtimes/java/docker.js +0 -40
- package/dist/module/src/server/runtimes/node/docker.js +0 -36
- package/dist/module/src/server/runtimes/node/esbuild.js +0 -35
- package/dist/module/src/server/runtimes/node/node.js +0 -37
- package/dist/module/src/server/runtimes/python/docker.js +0 -25
- package/dist/module/src/server/runtimes/ruby/docker.js +0 -28
- package/dist/module/src/server/runtimes/rust/docker.js +0 -29
- package/dist/module/src/server/runtimes/web/docker.js +0 -36
- package/dist/module/src/server/runtimes/web/esbuild.js +0 -24
- package/dist/module/src/server/runtimes/web/hoist.js +0 -11
- package/dist/module/src/server/runtimes/web/web.js +0 -119
- package/dist/module/src/server/serverClasees/Server.js +0 -40
- package/dist/module/src/server/serverClasees/Server_Base.js +0 -14
- package/dist/module/src/server/serverClasees/Server_Docker.js +0 -897
- package/dist/module/src/server/serverClasees/Server_FS.js +0 -119
- package/dist/module/src/server/serverClasees/Server_HTTP.js +0 -182
- package/dist/module/src/server/serverClasees/Server_WS.js +0 -258
- package/dist/module/src/server/serverManagers/DockerManager.js +0 -28
- package/dist/module/src/server/serverManagers/HttpManager.js +0 -110
- package/dist/module/src/server/serverManagers/WsManager.js +0 -226
- package/dist/module/src/server/serverManagers/fs.js +0 -32
- package/dist/module/src/server/serverManagers/tcp.js +0 -47
- package/dist/module/src/server/types.js +0 -1
- package/dist/module/src/testeranto.js +0 -40
- package/dist/module/src/vscode/TerminalManager.js +0 -92
- package/dist/module/src/vscode/TestTreeItem.js +0 -40
- package/dist/module/src/vscode/extension.js +0 -148
- package/dist/module/src/vscode/providers/FeaturesTreeDataProvider.js +0 -408
- package/dist/module/src/vscode/providers/FileTreeDataProvider.js +0 -153
- package/dist/module/src/vscode/providers/ProcessesTreeDataProvider.js +0 -233
- package/dist/module/src/vscode/providers/ResultsTreeDataProvider.js +0 -50
- package/dist/module/src/vscode/providers/TestTreeDataProvider.js +0 -272
- package/dist/module/src/vscode/types.js +0 -6
- package/dist/module/testeranto/runtimes/node/node.js +0 -5
- package/dist/module/testeranto/runtimes/web/web.js +0 -4
- package/dist/module/testeranto/testeranto.js +0 -68
- package/dist/module/tsconfig.module.tsbuildinfo +0 -1
- package/dist/prebuild/chunk-QLT7PNPK.mjs +0 -162
- package/dist/prebuild/esbuildConfigs/eslint-formatter-testeranto.mjs +0 -20
- package/dist/prebuild/init-docs.mjs +0 -56
- package/dist/prebuild/server/runtimes/node/node.mjs +0 -80
- package/dist/prebuild/server/runtimes/web/hoist.mjs +0 -12
- package/dist/prebuild/server/runtimes/web/web.mjs +0 -162
- package/dist/prebuild/testeranto-6SAYRVSE.mjs +0 -72
- package/dist/prebuild/testeranto.mjs +0 -1692
- package/dist/types/src/Init.d.ts +0 -2
- package/dist/types/src/Types.d.ts +0 -87
- package/dist/types/src/esbuildConfigs/consoleDetectorPlugin.d.ts +0 -2
- package/dist/types/src/esbuildConfigs/eslint-formatter-testeranto.d.ts +0 -2
- package/dist/types/src/esbuildConfigs/featuresPlugin.d.ts +0 -5
- package/dist/types/src/esbuildConfigs/index.d.ts +0 -3
- package/dist/types/src/esbuildConfigs/inputFilesPlugin.d.ts +0 -7
- package/dist/types/src/esbuildConfigs/nativeImportDetectorPlugin.d.ts +0 -2
- package/dist/types/src/esbuildConfigs/rebuildPlugin.d.ts +0 -6
- package/dist/types/src/init-docs.d.ts +0 -1
- package/dist/types/src/lib/tiposkripto/BaseGiven.d.ts +0 -42
- package/dist/types/src/lib/tiposkripto/BaseSuite.d.ts +0 -46
- package/dist/types/src/lib/tiposkripto/BaseThen.d.ts +0 -28
- package/dist/types/src/lib/tiposkripto/BaseTiposkripto.d.ts +0 -35
- package/dist/types/src/lib/tiposkripto/BaseWhen.d.ts +0 -27
- package/dist/types/src/lib/tiposkripto/CoreTypes.d.ts +0 -51
- package/dist/types/src/lib/tiposkripto/Node.d.ts +0 -9
- package/dist/types/src/lib/tiposkripto/Tiposkripto.d.ts +0 -5
- package/dist/types/src/lib/tiposkripto/Types.d.ts +0 -9
- package/dist/types/src/lib/tiposkripto/Web.d.ts +0 -9
- package/dist/types/src/lib/tiposkripto/abstractBase.test/MockGiven.d.ts +0 -9
- package/dist/types/src/lib/tiposkripto/abstractBase.test/MockThen.d.ts +0 -6
- package/dist/types/src/lib/tiposkripto/abstractBase.test/MockWhen.d.ts +0 -6
- package/dist/types/src/lib/tiposkripto/abstractBase.test/adapter.d.ts +0 -3
- package/dist/types/src/lib/tiposkripto/abstractBase.test/implementation.d.ts +0 -3
- package/dist/types/src/lib/tiposkripto/abstractBase.test/index.d.ts +0 -28
- package/dist/types/src/lib/tiposkripto/abstractBase.test/specification.d.ts +0 -3
- package/dist/types/src/lib/tiposkripto/abstractBase.test/types.d.ts +0 -39
- package/dist/types/src/lib/tiposkripto/index.d.ts +0 -56
- package/dist/types/src/runtimes.d.ts +0 -2
- package/dist/types/src/server/aider/configParser.d.ts +0 -11
- package/dist/types/src/server/aider/docker.d.ts +0 -2
- package/dist/types/src/server/getRunnables.d.ts +0 -3
- package/dist/types/src/server/htmlTemplate.d.ts +0 -2
- package/dist/types/src/server/nodeVersion.d.ts +0 -2
- package/dist/types/src/server/runtimes/common.d.ts +0 -12
- package/dist/types/src/server/runtimes/golang/docker.d.ts +0 -5
- package/dist/types/src/server/runtimes/java/docker.d.ts +0 -14
- package/dist/types/src/server/runtimes/node/docker.d.ts +0 -14
- package/dist/types/src/server/runtimes/node/esbuild.d.ts +0 -4
- package/dist/types/src/server/runtimes/node/node.d.ts +0 -1
- package/dist/types/src/server/runtimes/python/docker.d.ts +0 -14
- package/dist/types/src/server/runtimes/ruby/docker.d.ts +0 -14
- package/dist/types/src/server/runtimes/rust/docker.d.ts +0 -14
- package/dist/types/src/server/runtimes/web/docker.d.ts +0 -15
- package/dist/types/src/server/runtimes/web/esbuild.d.ts +0 -4
- package/dist/types/src/server/runtimes/web/hoist.d.ts +0 -1
- package/dist/types/src/server/runtimes/web/web.d.ts +0 -1
- package/dist/types/src/server/serverClasees/Server.d.ts +0 -8
- package/dist/types/src/server/serverClasees/Server_Base.d.ts +0 -9
- package/dist/types/src/server/serverClasees/Server_Docker.d.ts +0 -81
- package/dist/types/src/server/serverClasees/Server_FS.d.ts +0 -0
- package/dist/types/src/server/serverClasees/Server_HTTP.d.ts +0 -20
- package/dist/types/src/server/serverClasees/Server_WS.d.ts +0 -23
- package/dist/types/src/server/serverManagers/DockerManager.d.ts +0 -0
- package/dist/types/src/server/serverManagers/HttpManager.d.ts +0 -9
- package/dist/types/src/server/serverManagers/WsManager.d.ts +0 -10
- package/dist/types/src/server/serverManagers/fs.d.ts +0 -0
- package/dist/types/src/server/serverManagers/tcp.d.ts +0 -27
- package/dist/types/src/server/types.d.ts +0 -68
- package/dist/types/src/testeranto.d.ts +0 -1
- package/dist/types/src/vscode/TerminalManager.d.ts +0 -18
- package/dist/types/src/vscode/TestTreeItem.d.ts +0 -13
- package/dist/types/src/vscode/extension.d.ts +0 -3
- package/dist/types/src/vscode/providers/FeaturesTreeDataProvider.d.ts +0 -17
- package/dist/types/src/vscode/providers/FileTreeDataProvider.d.ts +0 -13
- package/dist/types/src/vscode/providers/ProcessesTreeDataProvider.d.ts +0 -23
- package/dist/types/src/vscode/providers/ResultsTreeDataProvider.d.ts +0 -10
- package/dist/types/src/vscode/providers/TestTreeDataProvider.d.ts +0 -16
- package/dist/types/src/vscode/types.d.ts +0 -14
- package/dist/types/testeranto/testeranto.d.ts +0 -3
- package/dist/types/tsconfig.types.tsbuildinfo +0 -1
- package/dist/vscode/extension.mjs +0 -5116
|
@@ -1,1692 +0,0 @@
|
|
|
1
|
-
// src/server/serverClasees/Server.ts
|
|
2
|
-
import fs3 from "fs";
|
|
3
|
-
import readline from "readline";
|
|
4
|
-
|
|
5
|
-
// src/server/serverClasees/Server_Docker.ts
|
|
6
|
-
import ansiColors from "ansi-colors";
|
|
7
|
-
import { exec, execSync, spawn } from "child_process";
|
|
8
|
-
import fs2 from "fs";
|
|
9
|
-
import yaml from "js-yaml";
|
|
10
|
-
import path2 from "path";
|
|
11
|
-
import { promisify } from "util";
|
|
12
|
-
|
|
13
|
-
// src/runtimes.ts
|
|
14
|
-
var RUN_TIMES = ["node", "web", "python", "golang", "java", "rust", "ruby"];
|
|
15
|
-
|
|
16
|
-
// src/server/runtimes/golang/docker.ts
|
|
17
|
-
var golangDockerComposeFile = (config, container_name) => {
|
|
18
|
-
return {
|
|
19
|
-
build: {
|
|
20
|
-
context: process.cwd(),
|
|
21
|
-
dockerfile: config[container_name].dockerfile
|
|
22
|
-
},
|
|
23
|
-
container_name,
|
|
24
|
-
environment: {
|
|
25
|
-
// NODE_ENV: "production",
|
|
26
|
-
// ...config.env,
|
|
27
|
-
},
|
|
28
|
-
working_dir: "/workspace",
|
|
29
|
-
volumes: [
|
|
30
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
31
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
32
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
33
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
34
|
-
],
|
|
35
|
-
command: golangBuildCommand()
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
|
-
var golangBuildCommand = () => {
|
|
39
|
-
return "go run src/server/runtimes/golang/main.go";
|
|
40
|
-
};
|
|
41
|
-
var golangBddCommand = () => {
|
|
42
|
-
const jsonStr = JSON.stringify({ ports: [1111] });
|
|
43
|
-
return `go run example/cmd/calculator-test`;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// src/server/runtimes/java/docker.ts
|
|
47
|
-
var javaDockerComposeFile = (config, container_name, fpath) => {
|
|
48
|
-
return {
|
|
49
|
-
build: {
|
|
50
|
-
context: process.cwd(),
|
|
51
|
-
dockerfile: config[container_name].dockerfile
|
|
52
|
-
},
|
|
53
|
-
container_name,
|
|
54
|
-
environment: {
|
|
55
|
-
NODE_ENV: "production",
|
|
56
|
-
...config.env
|
|
57
|
-
},
|
|
58
|
-
working_dir: "/workspace",
|
|
59
|
-
volumes: [
|
|
60
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
61
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
62
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
63
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
64
|
-
],
|
|
65
|
-
command: javaBuildCommand(fpath)
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
var javaBuildCommand = (fpath) => {
|
|
69
|
-
return `java src/server/runtimes/java/java.java /workspace/${fpath}`;
|
|
70
|
-
};
|
|
71
|
-
var javaBddCommand = (fpath) => {
|
|
72
|
-
return `java testeranto/bundles/java/${fpath} /workspace/java.java`;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// src/server/runtimes/node/docker.ts
|
|
76
|
-
var nodeDockerComposeFile = (config, container_name, projectConfigPath, nodeConfigPath, testName) => {
|
|
77
|
-
return {
|
|
78
|
-
build: {
|
|
79
|
-
context: process.cwd(),
|
|
80
|
-
dockerfile: config[container_name].dockerfile
|
|
81
|
-
},
|
|
82
|
-
container_name,
|
|
83
|
-
environment: {
|
|
84
|
-
NODE_ENV: "production",
|
|
85
|
-
...config.env
|
|
86
|
-
},
|
|
87
|
-
working_dir: "/workspace",
|
|
88
|
-
volumes: [
|
|
89
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
90
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
91
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
92
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
93
|
-
],
|
|
94
|
-
command: nodeBuildCommand(projectConfigPath, nodeConfigPath, testName)
|
|
95
|
-
};
|
|
96
|
-
};
|
|
97
|
-
var externalTests = true;
|
|
98
|
-
var nodeBuildCommand = (projectConfigPath, nodeConfigPath, testName) => {
|
|
99
|
-
if (externalTests) {
|
|
100
|
-
console.log("external tests", testName);
|
|
101
|
-
return `yarn tsx node_modules/testeranto/src/server/runtimes/node/node.ts /workspace/testeranto/testeranto.ts ${nodeConfigPath} ${testName}`;
|
|
102
|
-
} else {
|
|
103
|
-
console.log("not external tests");
|
|
104
|
-
return `yarn tsx src/server/runtimes/node/node.ts /workspace/testeranto/testeranto.ts /workspace/${nodeConfigPath} ${testName}`;
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
var nodeBddCommand = (fpath) => {
|
|
108
|
-
return `node ${fpath.split(".").slice(0, -1).concat("mjs").join(".")} /workspace/node.js`;
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
// src/server/runtimes/python/docker.ts
|
|
112
|
-
var pythonDockerComposeFile = (config, container_name, fpath) => {
|
|
113
|
-
return {
|
|
114
|
-
build: {
|
|
115
|
-
context: `${process.cwd()}/example`,
|
|
116
|
-
dockerfile: config[container_name].dockerfile
|
|
117
|
-
},
|
|
118
|
-
container_name,
|
|
119
|
-
environment: {
|
|
120
|
-
NODE_ENV: "production",
|
|
121
|
-
...config.env
|
|
122
|
-
},
|
|
123
|
-
working_dir: "/workspace",
|
|
124
|
-
volumes: [
|
|
125
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
126
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
127
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
128
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
129
|
-
],
|
|
130
|
-
command: pythonBuildCommand(fpath)
|
|
131
|
-
};
|
|
132
|
-
};
|
|
133
|
-
var pythonBuildCommand = (fpath) => {
|
|
134
|
-
return `python src/server/runtimes/python/pitono.py /workspace/${fpath}`;
|
|
135
|
-
};
|
|
136
|
-
var pythonBddCommand = (fpath) => {
|
|
137
|
-
const jsonStr = JSON.stringify({ ports: [1111] });
|
|
138
|
-
return `python ${fpath} '${jsonStr}'`;
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
// src/server/runtimes/ruby/docker.ts
|
|
142
|
-
var rubyDockerComposeFile = (config, container_name, fpath) => {
|
|
143
|
-
return {
|
|
144
|
-
build: {
|
|
145
|
-
context: process.cwd(),
|
|
146
|
-
dockerfile: config[container_name].dockerfile
|
|
147
|
-
},
|
|
148
|
-
container_name,
|
|
149
|
-
environment: {
|
|
150
|
-
NODE_ENV: "production",
|
|
151
|
-
...config.env
|
|
152
|
-
},
|
|
153
|
-
working_dir: "/workspace",
|
|
154
|
-
volumes: [
|
|
155
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
156
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
157
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
158
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
159
|
-
],
|
|
160
|
-
command: rubyBuildCommand(fpath)
|
|
161
|
-
};
|
|
162
|
-
};
|
|
163
|
-
var rubyBuildCommand = (fpath) => {
|
|
164
|
-
console.log("mark 1", fpath);
|
|
165
|
-
return `ruby src/server/runtimes/ruby/ruby.rb /workspace/${fpath}`;
|
|
166
|
-
};
|
|
167
|
-
var rubyBddCommand = (fpath) => {
|
|
168
|
-
const jsonStr = JSON.stringify({ ports: [1111] });
|
|
169
|
-
return `ruby ${fpath} '${jsonStr}'`;
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
// src/server/runtimes/rust/docker.ts
|
|
173
|
-
var rustDockerComposeFile = (config, container_name, fpath) => {
|
|
174
|
-
return {
|
|
175
|
-
build: {
|
|
176
|
-
context: `${process.cwd()}`,
|
|
177
|
-
dockerfile: config[container_name].dockerfile
|
|
178
|
-
},
|
|
179
|
-
container_name,
|
|
180
|
-
environment: {
|
|
181
|
-
NODE_ENV: "production",
|
|
182
|
-
...config.env
|
|
183
|
-
},
|
|
184
|
-
working_dir: "/workspace",
|
|
185
|
-
volumes: [
|
|
186
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
187
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
188
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
189
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
190
|
-
],
|
|
191
|
-
command: rustBuildCommand(fpath)
|
|
192
|
-
};
|
|
193
|
-
};
|
|
194
|
-
var rustBuildCommand = (fpath) => {
|
|
195
|
-
return `sh -c "CONFIG_PATH=/workspace/${fpath} cargo build --release && ./target/release/my_program"`;
|
|
196
|
-
};
|
|
197
|
-
var rustBddCommand = (fpath) => {
|
|
198
|
-
return `rustc testeranto/bundles/rust/${fpath} /workspace/rust.rs`;
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
// src/server/runtimes/web/docker.ts
|
|
202
|
-
var webDockerComposeFile = (config, container_name, fpath) => {
|
|
203
|
-
return {
|
|
204
|
-
platform: "linux/arm64",
|
|
205
|
-
build: {
|
|
206
|
-
context: process.cwd(),
|
|
207
|
-
dockerfile: config[container_name].dockerfile
|
|
208
|
-
},
|
|
209
|
-
container_name,
|
|
210
|
-
environment: {
|
|
211
|
-
// NODE_ENV: "production",
|
|
212
|
-
// ...config.env,
|
|
213
|
-
},
|
|
214
|
-
working_dir: "/workspace",
|
|
215
|
-
volumes: [
|
|
216
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
217
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
218
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
219
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
220
|
-
],
|
|
221
|
-
command: webBuildCommand(fpath)
|
|
222
|
-
};
|
|
223
|
-
};
|
|
224
|
-
var webBuildCommand = (fpath) => {
|
|
225
|
-
return `yarn tsx src/server/runtimes/web/web.ts /workspace/${fpath}`;
|
|
226
|
-
};
|
|
227
|
-
var webBddCommand = (fpath) => {
|
|
228
|
-
return `node dist/prebuild/server/runtimes/web/hoist.mjs `;
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
// src/server/serverClasees/Server_WS.ts
|
|
232
|
-
import { WebSocket, WebSocketServer } from "ws";
|
|
233
|
-
|
|
234
|
-
// src/server/serverManagers/WsManager.ts
|
|
235
|
-
var WsManager = class {
|
|
236
|
-
constructor() {
|
|
237
|
-
}
|
|
238
|
-
escapeXml(unsafe) {
|
|
239
|
-
if (!unsafe) return "";
|
|
240
|
-
return unsafe.replace(/[<>&'"]/g, (c) => {
|
|
241
|
-
switch (c) {
|
|
242
|
-
case "<":
|
|
243
|
-
return "<";
|
|
244
|
-
case ">":
|
|
245
|
-
return ">";
|
|
246
|
-
case "&":
|
|
247
|
-
return "&";
|
|
248
|
-
case "'":
|
|
249
|
-
return "'";
|
|
250
|
-
case '"':
|
|
251
|
-
return """;
|
|
252
|
-
default:
|
|
253
|
-
return c;
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
// Process message and return response data
|
|
258
|
-
processMessage(type, data, getProcessSummary, getProcessLogs) {
|
|
259
|
-
console.log("[WsManager] Processing message:", type);
|
|
260
|
-
switch (type) {
|
|
261
|
-
case "ping":
|
|
262
|
-
return {
|
|
263
|
-
type: "pong",
|
|
264
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
265
|
-
};
|
|
266
|
-
case "getProcesses":
|
|
267
|
-
if (getProcessSummary) {
|
|
268
|
-
const summary = getProcessSummary();
|
|
269
|
-
return {
|
|
270
|
-
type: "processes",
|
|
271
|
-
data: summary,
|
|
272
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
273
|
-
};
|
|
274
|
-
} else {
|
|
275
|
-
return {
|
|
276
|
-
type: "processes",
|
|
277
|
-
data: { processes: [], totalProcesses: 0, running: 0 },
|
|
278
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
case "getLogs":
|
|
282
|
-
const { processId } = data || {};
|
|
283
|
-
if (!processId) {
|
|
284
|
-
return {
|
|
285
|
-
type: "logs",
|
|
286
|
-
status: "error",
|
|
287
|
-
message: "Missing processId",
|
|
288
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
if (getProcessLogs) {
|
|
292
|
-
const logs = getProcessLogs(processId);
|
|
293
|
-
return {
|
|
294
|
-
type: "logs",
|
|
295
|
-
processId,
|
|
296
|
-
logs: logs.map((log) => {
|
|
297
|
-
let level = "info";
|
|
298
|
-
let source = "process";
|
|
299
|
-
let message = log;
|
|
300
|
-
const match = log.match(/\[(.*?)\] \[(.*?)\] (.*)/);
|
|
301
|
-
if (match) {
|
|
302
|
-
const timestamp = match[1];
|
|
303
|
-
source = match[2];
|
|
304
|
-
message = match[3];
|
|
305
|
-
if (source === "stderr" || source === "error") {
|
|
306
|
-
level = "error";
|
|
307
|
-
} else if (source === "warn") {
|
|
308
|
-
level = "warn";
|
|
309
|
-
} else if (source === "debug") {
|
|
310
|
-
level = "debug";
|
|
311
|
-
} else {
|
|
312
|
-
level = "info";
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
return {
|
|
316
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
317
|
-
level,
|
|
318
|
-
message,
|
|
319
|
-
source
|
|
320
|
-
};
|
|
321
|
-
}),
|
|
322
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
323
|
-
};
|
|
324
|
-
} else {
|
|
325
|
-
return {
|
|
326
|
-
type: "logs",
|
|
327
|
-
processId,
|
|
328
|
-
logs: [],
|
|
329
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
case "subscribeToLogs":
|
|
333
|
-
const { processId: subProcessId } = data || {};
|
|
334
|
-
if (!subProcessId) {
|
|
335
|
-
return {
|
|
336
|
-
type: "logSubscription",
|
|
337
|
-
status: "error",
|
|
338
|
-
message: "Missing processId",
|
|
339
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
return {
|
|
343
|
-
type: "logSubscription",
|
|
344
|
-
status: "subscribed",
|
|
345
|
-
processId: subProcessId,
|
|
346
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
347
|
-
};
|
|
348
|
-
case "sourceFilesUpdated":
|
|
349
|
-
const { testName, hash, files, runtime } = data || {};
|
|
350
|
-
if (!testName || !hash || !files || !runtime) {
|
|
351
|
-
return {
|
|
352
|
-
type: "sourceFilesUpdated",
|
|
353
|
-
status: "error",
|
|
354
|
-
message: "Missing required fields: testName, hash, files, or runtime",
|
|
355
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
return {
|
|
359
|
-
type: "sourceFilesUpdated",
|
|
360
|
-
status: "success",
|
|
361
|
-
testName,
|
|
362
|
-
runtime,
|
|
363
|
-
message: "Build update processed successfully",
|
|
364
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
365
|
-
};
|
|
366
|
-
case "getBuildListenerState":
|
|
367
|
-
return {
|
|
368
|
-
type: "buildListenerState",
|
|
369
|
-
status: "error",
|
|
370
|
-
message: "Build listener state not available",
|
|
371
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
372
|
-
};
|
|
373
|
-
case "getBuildEvents":
|
|
374
|
-
return {
|
|
375
|
-
type: "buildEvents",
|
|
376
|
-
status: "error",
|
|
377
|
-
message: "Build events not available",
|
|
378
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
379
|
-
};
|
|
380
|
-
default:
|
|
381
|
-
return {
|
|
382
|
-
type: "error",
|
|
383
|
-
message: `Unknown message type: ${type}`,
|
|
384
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
// Helper methods for specific message types
|
|
389
|
-
getProcessesResponse(processSummary) {
|
|
390
|
-
return {
|
|
391
|
-
type: "processes",
|
|
392
|
-
data: processSummary,
|
|
393
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
394
|
-
};
|
|
395
|
-
}
|
|
396
|
-
getLogsResponse(processId, logs) {
|
|
397
|
-
return {
|
|
398
|
-
type: "logs",
|
|
399
|
-
processId,
|
|
400
|
-
logs: logs.map((log) => {
|
|
401
|
-
let level = "info";
|
|
402
|
-
let source = "process";
|
|
403
|
-
let message = log;
|
|
404
|
-
const match = log.match(/\[(.*?)\] \[(.*?)\] (.*)/);
|
|
405
|
-
if (match) {
|
|
406
|
-
const timestamp = match[1];
|
|
407
|
-
source = match[2];
|
|
408
|
-
message = match[3];
|
|
409
|
-
if (source === "stderr" || source === "error") {
|
|
410
|
-
level = "error";
|
|
411
|
-
} else if (source === "warn") {
|
|
412
|
-
level = "warn";
|
|
413
|
-
} else if (source === "debug") {
|
|
414
|
-
level = "debug";
|
|
415
|
-
} else {
|
|
416
|
-
level = "info";
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
return {
|
|
420
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
421
|
-
level,
|
|
422
|
-
message,
|
|
423
|
-
source
|
|
424
|
-
};
|
|
425
|
-
}),
|
|
426
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
getSourceFilesUpdatedResponse(testName, runtime, status, message) {
|
|
430
|
-
return {
|
|
431
|
-
type: "sourceFilesUpdated",
|
|
432
|
-
status,
|
|
433
|
-
testName,
|
|
434
|
-
runtime,
|
|
435
|
-
message: message || "Build update processed successfully",
|
|
436
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
getErrorResponse(type, errorMessage) {
|
|
440
|
-
return {
|
|
441
|
-
type,
|
|
442
|
-
status: "error",
|
|
443
|
-
message: errorMessage,
|
|
444
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
getSuccessResponse(type, data) {
|
|
448
|
-
return {
|
|
449
|
-
type,
|
|
450
|
-
status: "success",
|
|
451
|
-
data,
|
|
452
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
|
|
457
|
-
// src/server/serverClasees/Server_HTTP.ts
|
|
458
|
-
import fs from "fs";
|
|
459
|
-
import http from "http";
|
|
460
|
-
import path from "path";
|
|
461
|
-
|
|
462
|
-
// src/server/serverManagers/tcp.ts
|
|
463
|
-
var CONTENT_TYPES = {
|
|
464
|
-
PLAIN: "text/plain",
|
|
465
|
-
HTML: "text/html",
|
|
466
|
-
JAVASCRIPT: "application/javascript",
|
|
467
|
-
CSS: "text/css",
|
|
468
|
-
JSON: "application/json",
|
|
469
|
-
PNG: "image/png",
|
|
470
|
-
JPEG: "image/jpeg",
|
|
471
|
-
GIF: "image/gif",
|
|
472
|
-
SVG: "image/svg+xml",
|
|
473
|
-
ICO: "image/x-icon",
|
|
474
|
-
WOFF: "font/woff",
|
|
475
|
-
WOFF2: "font/woff2",
|
|
476
|
-
TTF: "font/ttf",
|
|
477
|
-
EOT: "application/vnd.ms-fontobject",
|
|
478
|
-
XML: "application/xml",
|
|
479
|
-
PDF: "application/pdf",
|
|
480
|
-
ZIP: "application/zip",
|
|
481
|
-
OCTET_STREAM: "application/octet-stream"
|
|
482
|
-
};
|
|
483
|
-
function getContentType(filePath) {
|
|
484
|
-
if (filePath.endsWith(".html")) return CONTENT_TYPES.HTML;
|
|
485
|
-
else if (filePath.endsWith(".js") || filePath.endsWith(".mjs"))
|
|
486
|
-
return CONTENT_TYPES.JAVASCRIPT;
|
|
487
|
-
else if (filePath.endsWith(".css")) return CONTENT_TYPES.CSS;
|
|
488
|
-
else if (filePath.endsWith(".json")) return CONTENT_TYPES.JSON;
|
|
489
|
-
else if (filePath.endsWith(".png")) return CONTENT_TYPES.PNG;
|
|
490
|
-
else if (filePath.endsWith(".jpg") || filePath.endsWith(".jpeg"))
|
|
491
|
-
return CONTENT_TYPES.JPEG;
|
|
492
|
-
else if (filePath.endsWith(".gif")) return CONTENT_TYPES.GIF;
|
|
493
|
-
else if (filePath.endsWith(".svg")) return CONTENT_TYPES.SVG;
|
|
494
|
-
else return CONTENT_TYPES.PLAIN;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// src/server/serverClasees/Server_Base.ts
|
|
498
|
-
var Server_Base = class {
|
|
499
|
-
constructor(configs, mode2) {
|
|
500
|
-
this.configs = configs;
|
|
501
|
-
this.mode = mode2;
|
|
502
|
-
console.log(`[Base] ${this.configs}`);
|
|
503
|
-
}
|
|
504
|
-
async start() {
|
|
505
|
-
}
|
|
506
|
-
async stop() {
|
|
507
|
-
console.log(`[Server_Base] stop()`);
|
|
508
|
-
process.exit();
|
|
509
|
-
}
|
|
510
|
-
};
|
|
511
|
-
|
|
512
|
-
// src/server/serverClasees/Server_HTTP.ts
|
|
513
|
-
var Server_HTTP = class extends Server_Base {
|
|
514
|
-
constructor(configs, mode2) {
|
|
515
|
-
super(configs, mode2);
|
|
516
|
-
this.httpServer = http.createServer();
|
|
517
|
-
this.httpServer.on("error", (error) => {
|
|
518
|
-
console.error(`[HTTP] error:`, error);
|
|
519
|
-
});
|
|
520
|
-
this.httpServer.on("request", this.handleHttpRequest.bind(this));
|
|
521
|
-
}
|
|
522
|
-
async start() {
|
|
523
|
-
console.log(`[Server_HTTP] start()`);
|
|
524
|
-
super.start();
|
|
525
|
-
return new Promise((resolve) => {
|
|
526
|
-
this.httpServer.on("listening", () => {
|
|
527
|
-
const addr = this.httpServer.address();
|
|
528
|
-
console.log(`[HTTP] HTTP server is now listening on ${addr}`);
|
|
529
|
-
resolve();
|
|
530
|
-
});
|
|
531
|
-
});
|
|
532
|
-
}
|
|
533
|
-
async stop() {
|
|
534
|
-
console.log(`[Server_HTTP] stop()`);
|
|
535
|
-
this.httpServer.close(() => {
|
|
536
|
-
console.log("[HTTP] HTTP server closed");
|
|
537
|
-
});
|
|
538
|
-
await super.stop();
|
|
539
|
-
}
|
|
540
|
-
handleHttpRequest(req, res) {
|
|
541
|
-
console.log(`[Server_HTTP] handleHttpRequest(${req.url})`);
|
|
542
|
-
if (req.url && req.url.startsWith("/~/")) {
|
|
543
|
-
this.handleRouteRequest(req, res);
|
|
544
|
-
} else {
|
|
545
|
-
this.serveStaticFile(req, res);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
handleRouteRequest(req, res) {
|
|
549
|
-
console.log(`[Server_HTTP] handleRouteRequest(${req.url})`);
|
|
550
|
-
const routeName = this.http.routeName(req);
|
|
551
|
-
console.log(`[HTTP] Handling route: /~/${routeName}`);
|
|
552
|
-
const match = this.http.matchRoute(routeName, this.routes);
|
|
553
|
-
if (match) {
|
|
554
|
-
req.params = match.params;
|
|
555
|
-
try {
|
|
556
|
-
match.handler(req, res);
|
|
557
|
-
} catch (error) {
|
|
558
|
-
console.error(`[HTTP] Error in route handler for /~/${routeName}:`, error);
|
|
559
|
-
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
560
|
-
res.end(`Internal Server Error: ${error}`);
|
|
561
|
-
}
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
565
|
-
res.end(`Route not found: /~/${routeName}`);
|
|
566
|
-
}
|
|
567
|
-
serveStaticFile(req, res) {
|
|
568
|
-
console.log(`[Server_HTTP] serveStaticFile(${req.url})`);
|
|
569
|
-
if (!req.url) {
|
|
570
|
-
res.writeHead(400);
|
|
571
|
-
res.end("Bad Request");
|
|
572
|
-
return;
|
|
573
|
-
}
|
|
574
|
-
const normalizedPath = this.http.decodedPath(req);
|
|
575
|
-
if (normalizedPath.includes("..")) {
|
|
576
|
-
res.writeHead(403);
|
|
577
|
-
res.end("Forbidden: Directory traversal not allowed");
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
580
|
-
const projectRoot = process.cwd();
|
|
581
|
-
const filePath = path.join(projectRoot, normalizedPath);
|
|
582
|
-
if (!filePath.startsWith(path.resolve(projectRoot))) {
|
|
583
|
-
res.writeHead(403);
|
|
584
|
-
res.end("Forbidden");
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
fs.stat(filePath, (err, stats) => {
|
|
588
|
-
if (err) {
|
|
589
|
-
if (err.code === "ENOENT") {
|
|
590
|
-
res.writeHead(404);
|
|
591
|
-
res.end(`File not found: ${normalizedPath}`);
|
|
592
|
-
return;
|
|
593
|
-
} else {
|
|
594
|
-
res.writeHead(500);
|
|
595
|
-
res.end(`Server Error: ${err.message}`);
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
if (stats.isDirectory()) {
|
|
600
|
-
fs.readdir(filePath, (readErr, files) => {
|
|
601
|
-
if (readErr) {
|
|
602
|
-
res.writeHead(500);
|
|
603
|
-
res.end(`Server Error: ${readErr.message}`);
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
const items = files.map((file) => {
|
|
607
|
-
try {
|
|
608
|
-
const stat = fs.statSync(path.join(filePath, file));
|
|
609
|
-
const isDir = stat.isDirectory();
|
|
610
|
-
const slash = isDir ? "/" : "";
|
|
611
|
-
return `<li><a href="${path.join(
|
|
612
|
-
normalizedPath,
|
|
613
|
-
file
|
|
614
|
-
)}${slash}">${file}${slash}</a></li>`;
|
|
615
|
-
} catch {
|
|
616
|
-
return `<li><a href="${path.join(
|
|
617
|
-
normalizedPath,
|
|
618
|
-
file
|
|
619
|
-
)}">${file}</a></li>`;
|
|
620
|
-
}
|
|
621
|
-
}).join("");
|
|
622
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
623
|
-
res.end(`
|
|
624
|
-
<!DOCTYPE html>
|
|
625
|
-
<html>
|
|
626
|
-
<head><title>Directory listing for ${normalizedPath}</title></head>
|
|
627
|
-
<body>
|
|
628
|
-
<h1>Directory listing for ${normalizedPath}</h1>
|
|
629
|
-
<ul>
|
|
630
|
-
${items}
|
|
631
|
-
</ul>
|
|
632
|
-
</body>
|
|
633
|
-
</html>
|
|
634
|
-
`);
|
|
635
|
-
});
|
|
636
|
-
} else {
|
|
637
|
-
this.serveFile(filePath, res);
|
|
638
|
-
}
|
|
639
|
-
});
|
|
640
|
-
}
|
|
641
|
-
serveFile(filePath, res) {
|
|
642
|
-
console.log(`[Server_HTTP] serveFile(${filePath})`);
|
|
643
|
-
const contentType = getContentType(filePath) || CONTENT_TYPES.OCTET_STREAM;
|
|
644
|
-
fs.readFile(filePath, (err, data) => {
|
|
645
|
-
if (err) {
|
|
646
|
-
if (err.code === "ENOENT") {
|
|
647
|
-
res.writeHead(404);
|
|
648
|
-
res.end(`File not found: ${filePath}`);
|
|
649
|
-
} else {
|
|
650
|
-
res.writeHead(500);
|
|
651
|
-
res.end(`Server Error: ${err.message}`);
|
|
652
|
-
}
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
res.writeHead(200, { "Content-Type": contentType });
|
|
656
|
-
res.end(data);
|
|
657
|
-
});
|
|
658
|
-
}
|
|
659
|
-
// The route method is no longer abstract since we're using the routes() method
|
|
660
|
-
// This is kept for backward compatibility
|
|
661
|
-
router(a) {
|
|
662
|
-
return a;
|
|
663
|
-
}
|
|
664
|
-
};
|
|
665
|
-
|
|
666
|
-
// src/server/serverClasees/Server_WS.ts
|
|
667
|
-
var Server_WS = class extends Server_HTTP {
|
|
668
|
-
constructor(configs, mode2) {
|
|
669
|
-
super(configs, mode2);
|
|
670
|
-
this.wsClients = /* @__PURE__ */ new Set();
|
|
671
|
-
this.ws = new WebSocketServer({
|
|
672
|
-
noServer: true
|
|
673
|
-
});
|
|
674
|
-
this.wsManager = new WsManager();
|
|
675
|
-
this.setupWebSocketHandlers();
|
|
676
|
-
}
|
|
677
|
-
async start() {
|
|
678
|
-
console.log(`[Server_WS] start()`);
|
|
679
|
-
await super.start();
|
|
680
|
-
this.attachWebSocketToHttpServer(this.httpServer);
|
|
681
|
-
}
|
|
682
|
-
async stop() {
|
|
683
|
-
console.log(`[Server_WS] stop()`);
|
|
684
|
-
this.wsClients.forEach((client) => {
|
|
685
|
-
client.close();
|
|
686
|
-
});
|
|
687
|
-
this.wsClients.clear();
|
|
688
|
-
this.ws.close(() => {
|
|
689
|
-
console.log("[WebSocket] Server closed");
|
|
690
|
-
});
|
|
691
|
-
await super.stop();
|
|
692
|
-
}
|
|
693
|
-
escapeXml(unsafe) {
|
|
694
|
-
return this.wsManager.escapeXml(unsafe);
|
|
695
|
-
}
|
|
696
|
-
attachWebSocketToHttpServer(httpServer) {
|
|
697
|
-
httpServer.on("upgrade", (request, socket, head) => {
|
|
698
|
-
const pathname = new URL(request.url || "", `http://${request.headers.host}`).pathname;
|
|
699
|
-
if (pathname === "/ws") {
|
|
700
|
-
console.log("[WebSocket] Upgrade request for /ws");
|
|
701
|
-
this.ws.handleUpgrade(request, socket, head, (ws) => {
|
|
702
|
-
this.ws.emit("connection", ws, request);
|
|
703
|
-
});
|
|
704
|
-
} else {
|
|
705
|
-
socket.destroy();
|
|
706
|
-
}
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
broadcast(message) {
|
|
710
|
-
const data = typeof message === "string" ? message : JSON.stringify(message);
|
|
711
|
-
console.log(`[WebSocket] Broadcasting to ${this.wsClients.size} clients:`, message.type || message);
|
|
712
|
-
let sentCount = 0;
|
|
713
|
-
this.wsClients.forEach((client) => {
|
|
714
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
715
|
-
client.send(data);
|
|
716
|
-
sentCount++;
|
|
717
|
-
} else {
|
|
718
|
-
console.log(`[WebSocket] Client not open, state: ${client.readyState}`);
|
|
719
|
-
}
|
|
720
|
-
});
|
|
721
|
-
console.log(`[WebSocket] Sent to ${sentCount} clients`);
|
|
722
|
-
}
|
|
723
|
-
setupWebSocketHandlers() {
|
|
724
|
-
this.ws.on("connection", (ws, request) => {
|
|
725
|
-
console.log(`[WebSocket] New connection from ${request.socket.remoteAddress}`);
|
|
726
|
-
this.wsClients.add(ws);
|
|
727
|
-
ws.send(JSON.stringify({
|
|
728
|
-
type: "connected",
|
|
729
|
-
message: "Connected to Process Manager WebSocket",
|
|
730
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
731
|
-
}));
|
|
732
|
-
ws.send(JSON.stringify({
|
|
733
|
-
type: "processes",
|
|
734
|
-
data: this.getProcessSummary ? this.getProcessSummary() : { processes: [] },
|
|
735
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
736
|
-
}));
|
|
737
|
-
ws.on("message", (data) => {
|
|
738
|
-
try {
|
|
739
|
-
const message = JSON.parse(data.toString());
|
|
740
|
-
this.handleWebSocketMessage(ws, message);
|
|
741
|
-
} catch (error) {
|
|
742
|
-
console.error("[WebSocket] Error parsing message:", error);
|
|
743
|
-
ws.send(JSON.stringify({
|
|
744
|
-
type: "error",
|
|
745
|
-
message: "Invalid JSON message",
|
|
746
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
747
|
-
}));
|
|
748
|
-
}
|
|
749
|
-
});
|
|
750
|
-
ws.on("close", () => {
|
|
751
|
-
console.log("[WebSocket] Client disconnected");
|
|
752
|
-
this.wsClients.delete(ws);
|
|
753
|
-
});
|
|
754
|
-
ws.on("error", (error) => {
|
|
755
|
-
console.error("[WebSocket] Error:", error);
|
|
756
|
-
this.wsClients.delete(ws);
|
|
757
|
-
});
|
|
758
|
-
});
|
|
759
|
-
this.ws.on("error", (error) => {
|
|
760
|
-
console.error("[WebSocket] Server error:", error);
|
|
761
|
-
});
|
|
762
|
-
this.ws.on("close", () => {
|
|
763
|
-
console.log("[WebSocket] Server closing...");
|
|
764
|
-
this.wsClients.clear();
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
handleWebSocketMessage(ws, message) {
|
|
768
|
-
console.log("[WebSocket] Received message:", message.type);
|
|
769
|
-
const response = this.wsManager.processMessage(
|
|
770
|
-
message.type,
|
|
771
|
-
message.data,
|
|
772
|
-
() => this.getProcessSummary(),
|
|
773
|
-
(processId) => {
|
|
774
|
-
const processManager = this;
|
|
775
|
-
if (typeof processManager.getProcessLogs === "function") {
|
|
776
|
-
return processManager.getProcessLogs(processId);
|
|
777
|
-
}
|
|
778
|
-
return [];
|
|
779
|
-
}
|
|
780
|
-
);
|
|
781
|
-
ws.send(JSON.stringify(response));
|
|
782
|
-
switch (message.type) {
|
|
783
|
-
case "sourceFilesUpdated":
|
|
784
|
-
this.handleSourceFilesUpdatedSideEffects(ws, message.data, response);
|
|
785
|
-
break;
|
|
786
|
-
case "getBuildListenerState":
|
|
787
|
-
this.handleGetBuildListenerStateSideEffects(ws);
|
|
788
|
-
break;
|
|
789
|
-
case "getBuildEvents":
|
|
790
|
-
this.handleGetBuildEventsSideEffects(ws);
|
|
791
|
-
break;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
handleSourceFilesUpdatedSideEffects(ws, data, response) {
|
|
795
|
-
const { testName, hash, files, runtime } = data || {};
|
|
796
|
-
if (!testName || !hash || !files || !runtime) {
|
|
797
|
-
return;
|
|
798
|
-
}
|
|
799
|
-
console.log(`[WebSocket] Forwarding source files update to build listener for test: ${testName} (runtime: ${runtime})`);
|
|
800
|
-
if (typeof this.sourceFilesUpdated === "function") {
|
|
801
|
-
console.log(`[WebSocket] sourceFilesUpdated method found, calling it`);
|
|
802
|
-
try {
|
|
803
|
-
this.sourceFilesUpdated(testName, hash, files, runtime);
|
|
804
|
-
console.log(`[WebSocket] sourceFilesUpdated called successfully`);
|
|
805
|
-
this.broadcast({
|
|
806
|
-
type: "sourceFilesUpdated",
|
|
807
|
-
testName,
|
|
808
|
-
hash,
|
|
809
|
-
files,
|
|
810
|
-
runtime,
|
|
811
|
-
status: "processed",
|
|
812
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
813
|
-
message: "Source files update processed successfully"
|
|
814
|
-
});
|
|
815
|
-
if (response.status === "success") {
|
|
816
|
-
ws.send(JSON.stringify({
|
|
817
|
-
type: "sourceFilesUpdated",
|
|
818
|
-
status: "processed",
|
|
819
|
-
testName,
|
|
820
|
-
runtime,
|
|
821
|
-
message: "Build update processed and broadcasted successfully",
|
|
822
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
823
|
-
}));
|
|
824
|
-
}
|
|
825
|
-
} catch (error) {
|
|
826
|
-
console.error("[WebSocket] Error processing source files update:", error);
|
|
827
|
-
ws.send(JSON.stringify({
|
|
828
|
-
type: "sourceFilesUpdated",
|
|
829
|
-
status: "error",
|
|
830
|
-
testName,
|
|
831
|
-
runtime,
|
|
832
|
-
message: `Error processing build update: ${error}`,
|
|
833
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
834
|
-
}));
|
|
835
|
-
}
|
|
836
|
-
} else {
|
|
837
|
-
console.warn("[WebSocket] sourceFilesUpdated method not available on this instance");
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
handleGetBuildListenerStateSideEffects(ws) {
|
|
841
|
-
console.log("[WebSocket] Handling getBuildListenerState request");
|
|
842
|
-
if (typeof this.getBuildListenerState === "function") {
|
|
843
|
-
try {
|
|
844
|
-
const state = this.getBuildListenerState();
|
|
845
|
-
ws.send(JSON.stringify({
|
|
846
|
-
type: "buildListenerState",
|
|
847
|
-
data: state,
|
|
848
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
849
|
-
}));
|
|
850
|
-
} catch (error) {
|
|
851
|
-
console.error("[WebSocket] Error getting build listener state:", error);
|
|
852
|
-
ws.send(JSON.stringify({
|
|
853
|
-
type: "buildListenerState",
|
|
854
|
-
status: "error",
|
|
855
|
-
message: `Error getting build listener state: ${error}`,
|
|
856
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
857
|
-
}));
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
handleGetBuildEventsSideEffects(ws) {
|
|
862
|
-
console.log("[WebSocket] Handling getBuildEvents request");
|
|
863
|
-
if (typeof this.getBuildEvents === "function") {
|
|
864
|
-
try {
|
|
865
|
-
const events = this.getBuildEvents();
|
|
866
|
-
ws.send(JSON.stringify({
|
|
867
|
-
type: "buildEvents",
|
|
868
|
-
events,
|
|
869
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
870
|
-
}));
|
|
871
|
-
} catch (error) {
|
|
872
|
-
console.error("[WebSocket] Error getting build events:", error);
|
|
873
|
-
ws.send(JSON.stringify({
|
|
874
|
-
type: "buildEvents",
|
|
875
|
-
status: "error",
|
|
876
|
-
message: `Error getting build events: ${error}`,
|
|
877
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
878
|
-
}));
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
handleGetProcesses(ws) {
|
|
883
|
-
if (typeof this.getProcessSummary === "function") {
|
|
884
|
-
const summary = this.getProcessSummary();
|
|
885
|
-
ws.send(JSON.stringify({
|
|
886
|
-
type: "processes",
|
|
887
|
-
data: summary,
|
|
888
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
889
|
-
}));
|
|
890
|
-
} else {
|
|
891
|
-
ws.send(JSON.stringify({
|
|
892
|
-
type: "processes",
|
|
893
|
-
data: { processes: [], message: "getProcessSummary not available" },
|
|
894
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
895
|
-
}));
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
};
|
|
899
|
-
|
|
900
|
-
// src/server/serverClasees/Server_Docker.ts
|
|
901
|
-
var Server_Docker = class extends Server_WS {
|
|
902
|
-
constructor(configs, mode2) {
|
|
903
|
-
super(configs, mode2);
|
|
904
|
-
this.logProcesses = /* @__PURE__ */ new Map();
|
|
905
|
-
}
|
|
906
|
-
BaseCompose(services) {
|
|
907
|
-
return {
|
|
908
|
-
services,
|
|
909
|
-
volumes: {
|
|
910
|
-
node_modules: {
|
|
911
|
-
driver: "local"
|
|
912
|
-
}
|
|
913
|
-
},
|
|
914
|
-
networks: {
|
|
915
|
-
allTests_network: {
|
|
916
|
-
driver: "bridge"
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
};
|
|
920
|
-
}
|
|
921
|
-
staticTestDockerComposeFile(runtime, container_name, command) {
|
|
922
|
-
let dockerfilePath = "";
|
|
923
|
-
for (const [key, value] of Object.entries(this.configs.runtimes)) {
|
|
924
|
-
if (value.runtime === runtime) {
|
|
925
|
-
dockerfilePath = value.dockerfile;
|
|
926
|
-
break;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
if (!dockerfilePath) {
|
|
930
|
-
throw `[Docker] [staticTestDockerComposeFile] no dockerfile found for ${dockerfilePath}, ${Object.entries(this.configs)}`;
|
|
931
|
-
}
|
|
932
|
-
return {
|
|
933
|
-
build: {
|
|
934
|
-
context: process.cwd(),
|
|
935
|
-
dockerfile: dockerfilePath
|
|
936
|
-
},
|
|
937
|
-
container_name,
|
|
938
|
-
environment: {
|
|
939
|
-
// NODE_ENV: "production",
|
|
940
|
-
// ...config.env,
|
|
941
|
-
},
|
|
942
|
-
working_dir: "/workspace",
|
|
943
|
-
command,
|
|
944
|
-
networks: ["allTests_network"]
|
|
945
|
-
};
|
|
946
|
-
}
|
|
947
|
-
bddTestDockerComposeFile(runtime, container_name, command) {
|
|
948
|
-
let dockerfilePath = "";
|
|
949
|
-
for (const [key, value] of Object.entries(this.configs.runtimes)) {
|
|
950
|
-
if (value.runtime === runtime) {
|
|
951
|
-
dockerfilePath = value.dockerfile;
|
|
952
|
-
break;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
if (!dockerfilePath) {
|
|
956
|
-
throw `[Docker] [bddTestDockerComposeFile] no dockerfile found for ${dockerfilePath}, ${Object.entries(this.configs)}`;
|
|
957
|
-
}
|
|
958
|
-
const service = {
|
|
959
|
-
build: {
|
|
960
|
-
context: process.cwd(),
|
|
961
|
-
dockerfile: dockerfilePath
|
|
962
|
-
},
|
|
963
|
-
container_name,
|
|
964
|
-
environment: {
|
|
965
|
-
// NODE_ENV: "production",
|
|
966
|
-
// ...config.env,
|
|
967
|
-
},
|
|
968
|
-
working_dir: "/workspace",
|
|
969
|
-
volumes: [
|
|
970
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
971
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
972
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
973
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
974
|
-
],
|
|
975
|
-
command,
|
|
976
|
-
networks: ["allTests_network"]
|
|
977
|
-
};
|
|
978
|
-
return service;
|
|
979
|
-
}
|
|
980
|
-
aiderDockerComposeFile(container_name) {
|
|
981
|
-
return {
|
|
982
|
-
build: {
|
|
983
|
-
context: process.cwd(),
|
|
984
|
-
dockerfile: "aider.Dockerfile"
|
|
985
|
-
},
|
|
986
|
-
container_name,
|
|
987
|
-
environment: {
|
|
988
|
-
// NODE_ENV: "production",
|
|
989
|
-
// ...config.env,
|
|
990
|
-
},
|
|
991
|
-
working_dir: "/workspace",
|
|
992
|
-
command: "aider",
|
|
993
|
-
networks: ["allTests_network"]
|
|
994
|
-
};
|
|
995
|
-
}
|
|
996
|
-
generateServices() {
|
|
997
|
-
const services = {};
|
|
998
|
-
console.log("mark1");
|
|
999
|
-
const runTimeToCompose = {
|
|
1000
|
-
"node": [nodeDockerComposeFile, nodeBuildCommand, nodeBddCommand],
|
|
1001
|
-
"web": [webDockerComposeFile, webBuildCommand, webBddCommand],
|
|
1002
|
-
"python": [pythonDockerComposeFile, pythonBuildCommand, pythonBddCommand],
|
|
1003
|
-
"golang": [golangDockerComposeFile, golangBuildCommand, golangBddCommand],
|
|
1004
|
-
"ruby": [rubyDockerComposeFile, rubyBuildCommand, rubyBddCommand],
|
|
1005
|
-
"rust": [rustDockerComposeFile, rustBuildCommand, rustBddCommand],
|
|
1006
|
-
"java": [javaDockerComposeFile, javaBuildCommand, javaBddCommand]
|
|
1007
|
-
};
|
|
1008
|
-
for (const [runtimeTestsName, runtimeTests] of Object.entries(this.configs.runtimes)) {
|
|
1009
|
-
const runtime = runtimeTests.runtime;
|
|
1010
|
-
const dockerfile = runtimeTests.dockerfile;
|
|
1011
|
-
const buildOptions = runtimeTests.buildOptions;
|
|
1012
|
-
const testsObj = runtimeTests.tests;
|
|
1013
|
-
for (const [t, c] of Object.entries(this.configs.runtimes)) {
|
|
1014
|
-
if (c.runtime === runtime) {
|
|
1015
|
-
if (RUN_TIMES.includes(runtime)) {
|
|
1016
|
-
const buildCommand = runTimeToCompose[runtime][1](
|
|
1017
|
-
buildOptions,
|
|
1018
|
-
c.buildOptions,
|
|
1019
|
-
runtimeTestsName
|
|
1020
|
-
);
|
|
1021
|
-
const builderServiceName = `${runtime}-builder`;
|
|
1022
|
-
let dockerfilePath = dockerfile;
|
|
1023
|
-
const fullDockerfilePath = path2.join(process.cwd(), dockerfilePath);
|
|
1024
|
-
if (!fs2.existsSync(fullDockerfilePath)) {
|
|
1025
|
-
throw `[Server_Docker] Dockerfile not found at ${fullDockerfilePath}`;
|
|
1026
|
-
}
|
|
1027
|
-
services[builderServiceName] = {
|
|
1028
|
-
build: {
|
|
1029
|
-
context: process.cwd(),
|
|
1030
|
-
dockerfile: dockerfilePath
|
|
1031
|
-
},
|
|
1032
|
-
container_name: builderServiceName,
|
|
1033
|
-
environment: {},
|
|
1034
|
-
working_dir: "/workspace",
|
|
1035
|
-
volumes: [
|
|
1036
|
-
`${process.cwd()}/src:/workspace/src`,
|
|
1037
|
-
`${process.cwd()}/example:/workspace/example`,
|
|
1038
|
-
`${process.cwd()}/dist:/workspace/dist`,
|
|
1039
|
-
`${process.cwd()}/testeranto:/workspace/testeranto`
|
|
1040
|
-
],
|
|
1041
|
-
command: buildCommand,
|
|
1042
|
-
networks: ["allTests_network"]
|
|
1043
|
-
};
|
|
1044
|
-
for (const tName of testsObj) {
|
|
1045
|
-
const cleanTestName = tName.toLowerCase().replaceAll("/", "_").replaceAll(".", "-").replace(/[^a-z0-9_-]/g, "");
|
|
1046
|
-
const uid = `${runtimeTestsName.toLowerCase()}-${cleanTestName}`;
|
|
1047
|
-
const bddCommandFunc = runTimeToCompose[runtime][2];
|
|
1048
|
-
const filePath = `testeranto/bundles/allTests/${runtime}/${tName}`;
|
|
1049
|
-
const command = bddCommandFunc(filePath);
|
|
1050
|
-
console.log("wtf command", command);
|
|
1051
|
-
services[`${uid}-bdd`] = this.bddTestDockerComposeFile(runtime, `${uid}-bdd`, command);
|
|
1052
|
-
services[`${uid}-aider`] = this.aiderDockerComposeFile(`${uid}-aider`);
|
|
1053
|
-
}
|
|
1054
|
-
} else {
|
|
1055
|
-
throw `unknown runtime ${runtime}`;
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
for (const serviceName in services) {
|
|
1061
|
-
if (!services[serviceName].networks) {
|
|
1062
|
-
services[serviceName].networks = ["allTests_network"];
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
return services;
|
|
1066
|
-
}
|
|
1067
|
-
autogenerateStamp(x) {
|
|
1068
|
-
return `# This file is autogenerated. Do not edit it directly
|
|
1069
|
-
${x}
|
|
1070
|
-
`;
|
|
1071
|
-
}
|
|
1072
|
-
getUpCommand() {
|
|
1073
|
-
return `docker compose up -d`;
|
|
1074
|
-
}
|
|
1075
|
-
getDownCommand() {
|
|
1076
|
-
return `docker compose down -v --remove-orphans`;
|
|
1077
|
-
}
|
|
1078
|
-
getPsCommand() {
|
|
1079
|
-
return `docker compose ps`;
|
|
1080
|
-
}
|
|
1081
|
-
getLogsCommand(serviceName, tail = 100) {
|
|
1082
|
-
const base = `docker compose logs --no-color --tail=${tail}`;
|
|
1083
|
-
return serviceName ? `${base} ${serviceName}` : base;
|
|
1084
|
-
}
|
|
1085
|
-
getConfigServicesCommand() {
|
|
1086
|
-
return `docker compose config --services`;
|
|
1087
|
-
}
|
|
1088
|
-
getBuildCommand() {
|
|
1089
|
-
return `docker compose build`;
|
|
1090
|
-
}
|
|
1091
|
-
getStartCommand() {
|
|
1092
|
-
return `docker compose start`;
|
|
1093
|
-
}
|
|
1094
|
-
// private async waitForContainerExists(serviceName: string, maxAttempts: number = 30, delayMs: number = 1000): Promise<boolean> {
|
|
1095
|
-
// for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1096
|
-
// try {
|
|
1097
|
-
// const cmd = `docker compose -f "testeranto/docker-compose.yml" ps -q ${serviceName}`;
|
|
1098
|
-
// const { execSync } = require('child_process');
|
|
1099
|
-
// const containerId = execSync(cmd, {
|
|
1100
|
-
// // cwd:this.dockerManager.cwd
|
|
1101
|
-
// }).toString().trim();
|
|
1102
|
-
// if (containerId && containerId.length > 0) {
|
|
1103
|
-
// console.log(`[Server_Docker] Container for ${serviceName} exists with ID: ${containerId.substring(0, 12)}`);
|
|
1104
|
-
// return true;
|
|
1105
|
-
// }
|
|
1106
|
-
// } catch (error) {
|
|
1107
|
-
// // Container doesn't exist yet or command failed
|
|
1108
|
-
// }
|
|
1109
|
-
// if (attempt < maxAttempts) {
|
|
1110
|
-
// await new Promise(resolve => setTimeout(resolve, delayMs));
|
|
1111
|
-
// }
|
|
1112
|
-
// }
|
|
1113
|
-
// console.warn(`[Server_Docker] Container for ${serviceName} did not appear after ${maxAttempts} attempts`);
|
|
1114
|
-
// return false;
|
|
1115
|
-
// }
|
|
1116
|
-
async startServiceLogging(serviceName, runtime) {
|
|
1117
|
-
const reportDir = path2.join(
|
|
1118
|
-
process.cwd(),
|
|
1119
|
-
"testeranto",
|
|
1120
|
-
"reports",
|
|
1121
|
-
"allTests",
|
|
1122
|
-
"example",
|
|
1123
|
-
runtime
|
|
1124
|
-
);
|
|
1125
|
-
try {
|
|
1126
|
-
fs2.mkdirSync(reportDir, { recursive: true });
|
|
1127
|
-
} catch (error) {
|
|
1128
|
-
console.error(`[Server_Docker] Failed to create report directory ${reportDir}: ${error.message}`);
|
|
1129
|
-
return;
|
|
1130
|
-
}
|
|
1131
|
-
const logFilePath = path2.join(reportDir, `${serviceName}.log`);
|
|
1132
|
-
const exitCodeFilePath = path2.join(reportDir, `${serviceName}.exitcode`);
|
|
1133
|
-
const logScript = `
|
|
1134
|
-
# Wait for container to exist
|
|
1135
|
-
for i in {1..30}; do
|
|
1136
|
-
if docker compose -f "testeranto/docker-compose.yml" ps -q ${serviceName} > /dev/null 2>&1; then
|
|
1137
|
-
break
|
|
1138
|
-
fi
|
|
1139
|
-
sleep 1
|
|
1140
|
-
done
|
|
1141
|
-
# Capture logs from the beginning
|
|
1142
|
-
docker compose -f "testeranto/docker-compose.yml" logs --no-color -f ${serviceName}
|
|
1143
|
-
`;
|
|
1144
|
-
console.log(`[Server_Docker] Starting log capture for ${serviceName} to ${logFilePath}`);
|
|
1145
|
-
const logStream = fs2.createWriteStream(logFilePath, { flags: "a" });
|
|
1146
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1147
|
-
logStream.write(`=== Log started at ${timestamp} for service ${serviceName} ===
|
|
1148
|
-
|
|
1149
|
-
`);
|
|
1150
|
-
const child = spawn("bash", ["-c", logScript], {
|
|
1151
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
1152
|
-
// cwd: this.dockerManager.cwd
|
|
1153
|
-
});
|
|
1154
|
-
let containerId = null;
|
|
1155
|
-
try {
|
|
1156
|
-
const containerIdCmd = `docker compose -f "testeranto/docker-compose.yml" ps -q ${serviceName}`;
|
|
1157
|
-
containerId = execSync(containerIdCmd, {
|
|
1158
|
-
// cwd: this.dockerManager.cwd
|
|
1159
|
-
}).toString().trim();
|
|
1160
|
-
} catch (error) {
|
|
1161
|
-
console.warn(`[Server_Docker] Could not get container ID for ${serviceName}, will track by service name`);
|
|
1162
|
-
}
|
|
1163
|
-
child.stdout?.on("data", (data) => {
|
|
1164
|
-
logStream.write(data);
|
|
1165
|
-
});
|
|
1166
|
-
child.stderr?.on("data", (data) => {
|
|
1167
|
-
logStream.write(data);
|
|
1168
|
-
});
|
|
1169
|
-
child.on("error", (error) => {
|
|
1170
|
-
console.error(`[Server_Docker] Log process error for ${serviceName}:`, error);
|
|
1171
|
-
logStream.write(`
|
|
1172
|
-
=== Log process error: ${error.message} ===
|
|
1173
|
-
`);
|
|
1174
|
-
logStream.end();
|
|
1175
|
-
fs2.writeFileSync(exitCodeFilePath, "-1");
|
|
1176
|
-
});
|
|
1177
|
-
child.on("close", (code) => {
|
|
1178
|
-
const endTimestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1179
|
-
logStream.write(`
|
|
1180
|
-
=== Log ended at ${endTimestamp}, process exited with code ${code} ===
|
|
1181
|
-
`);
|
|
1182
|
-
logStream.end();
|
|
1183
|
-
console.log(`[Server_Docker] Log process for ${serviceName} exited with code ${code}`);
|
|
1184
|
-
fs2.writeFileSync(exitCodeFilePath, code?.toString() || "0");
|
|
1185
|
-
this.captureContainerExitCode(serviceName, reportDir);
|
|
1186
|
-
if (containerId) {
|
|
1187
|
-
this.logProcesses.delete(containerId);
|
|
1188
|
-
} else {
|
|
1189
|
-
for (const [id, proc] of this.logProcesses.entries()) {
|
|
1190
|
-
if (proc.serviceName === serviceName) {
|
|
1191
|
-
this.logProcesses.delete(id);
|
|
1192
|
-
break;
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
});
|
|
1197
|
-
const trackingKey = containerId || serviceName;
|
|
1198
|
-
this.logProcesses.set(trackingKey, { process: child, serviceName });
|
|
1199
|
-
}
|
|
1200
|
-
async captureContainerExitCode(serviceName, reportDir) {
|
|
1201
|
-
try {
|
|
1202
|
-
const containerIdCmd = `docker compose -f "testeranto/docker-compose.yml" ps -a -q ${serviceName}`;
|
|
1203
|
-
const containerId = execSync(containerIdCmd, {
|
|
1204
|
-
// cwd: this.dockerManager.cwd
|
|
1205
|
-
}).toString().trim();
|
|
1206
|
-
if (containerId) {
|
|
1207
|
-
const inspectCmd = `docker inspect --format='{{.State.ExitCode}}' ${containerId}`;
|
|
1208
|
-
const exitCode = execSync(inspectCmd, {
|
|
1209
|
-
// cwd: this.dockerManager.cwd
|
|
1210
|
-
}).toString().trim();
|
|
1211
|
-
const containerExitCodeFilePath = path2.join(reportDir, `${serviceName}.container.exitcode`);
|
|
1212
|
-
fs2.writeFileSync(containerExitCodeFilePath, exitCode);
|
|
1213
|
-
console.log(`[Server_Docker] Container ${serviceName} (${containerId.substring(0, 12)}) exited with code ${exitCode}`);
|
|
1214
|
-
const statusCmd = `docker inspect --format='{{.State.Status}}' ${containerId}`;
|
|
1215
|
-
const status = execSync(statusCmd, {
|
|
1216
|
-
// cwd: this.dockerManager.cwd
|
|
1217
|
-
}).toString().trim();
|
|
1218
|
-
const statusFilePath = path2.join(reportDir, `${serviceName}.container.status`);
|
|
1219
|
-
fs2.writeFileSync(statusFilePath, status);
|
|
1220
|
-
} else {
|
|
1221
|
-
console.debug(`[Server_Docker] No container found for service ${serviceName}`);
|
|
1222
|
-
}
|
|
1223
|
-
} catch (error) {
|
|
1224
|
-
console.debug(`[Server_Docker] Could not capture container exit code for ${serviceName}: ${error.message}`);
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
async start() {
|
|
1228
|
-
console.log(`[Server_Docker] start()`);
|
|
1229
|
-
super.start();
|
|
1230
|
-
await this.setupDockerCompose();
|
|
1231
|
-
const baseReportsDir = path2.join(process.cwd(), "testeranto", "reports");
|
|
1232
|
-
try {
|
|
1233
|
-
fs2.mkdirSync(baseReportsDir, { recursive: true });
|
|
1234
|
-
console.log(`[Server_Docker] Created base reports directory: ${baseReportsDir}`);
|
|
1235
|
-
} catch (error) {
|
|
1236
|
-
console.error(`[Server_Docker] Failed to create base reports directory ${baseReportsDir}: ${error.message}`);
|
|
1237
|
-
}
|
|
1238
|
-
console.log(`[Server_Docker] Dropping everything...`);
|
|
1239
|
-
try {
|
|
1240
|
-
const downCmd = `docker compose -f "testeranto/docker-compose.yml" down -v --remove-orphans`;
|
|
1241
|
-
console.log(`[Server_Docker] Running: ${downCmd}`);
|
|
1242
|
-
await this.spawnPromise(downCmd);
|
|
1243
|
-
console.log(`[Server_Docker] Docker compose down completed`);
|
|
1244
|
-
} catch (error) {
|
|
1245
|
-
console.log(`[Server_Docker] Docker compose down noted: ${error.message}`);
|
|
1246
|
-
}
|
|
1247
|
-
for (const runtime of RUN_TIMES) {
|
|
1248
|
-
const serviceName = `${runtime}-builder`;
|
|
1249
|
-
console.log(`[Server_Docker] Starting builder service: ${serviceName}`);
|
|
1250
|
-
try {
|
|
1251
|
-
await this.spawnPromise(`docker compose -f "testeranto/docker-compose.yml" up -d ${serviceName}`);
|
|
1252
|
-
this.startServiceLogging(serviceName, runtime).catch((error) => console.error(`[Server_Docker] Failed to start logging for ${serviceName}:`, error));
|
|
1253
|
-
this.captureExistingLogs(serviceName, runtime);
|
|
1254
|
-
} catch (error) {
|
|
1255
|
-
console.error(`[Server_Docker] Failed to start ${serviceName}: ${error.message}`);
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
console.log(`[Server_Docker] Starting browser service...`);
|
|
1259
|
-
try {
|
|
1260
|
-
await this.spawnPromise(`docker compose -f "testeranto/docker-compose.yml" up -d browser`);
|
|
1261
|
-
} catch (error) {
|
|
1262
|
-
console.error(`[Server_Docker] Failed to start browser service: ${error.message}`);
|
|
1263
|
-
}
|
|
1264
|
-
console.log(`[Server_Docker] Waiting for browser container to be healthy...`);
|
|
1265
|
-
await this.waitForContainerHealthy("browser-allTests", 6e4);
|
|
1266
|
-
for (const [configKey, configValue] of Object.entries(this.configs.runtimes)) {
|
|
1267
|
-
const runtime = configValue.runtime;
|
|
1268
|
-
const tests = configValue.tests;
|
|
1269
|
-
console.log(`[Server_Docker] Found tests for ${runtime}:`, JSON.stringify(tests));
|
|
1270
|
-
for (const testName of tests) {
|
|
1271
|
-
const uid = `${configKey}-${testName.toLowerCase().replaceAll("/", "_").replaceAll(".", "-")}`;
|
|
1272
|
-
const aiderServiceName = `${uid}-aider`;
|
|
1273
|
-
console.log(`[Server_Docker] Starting aider service: ${aiderServiceName} for test ${testName}`);
|
|
1274
|
-
try {
|
|
1275
|
-
await this.spawnPromise(`docker compose -f "testeranto/docker-compose.yml" up -d ${aiderServiceName}`);
|
|
1276
|
-
this.startServiceLogging(aiderServiceName, runtime).catch((error) => console.error(`[Server_Docker] Failed to start logging for ${aiderServiceName}:`, error));
|
|
1277
|
-
this.captureExistingLogs(aiderServiceName, runtime).catch((error) => console.error(`[Server_Docker] Failed to capture existing logs for ${aiderServiceName}:`, error));
|
|
1278
|
-
} catch (error) {
|
|
1279
|
-
console.error(`[Server_Docker] Failed to start ${aiderServiceName}: ${error.message}`);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
}
|
|
1283
|
-
for (const [configKey, configValue] of Object.entries(this.configs.runtimes)) {
|
|
1284
|
-
const runtime = configValue.runtime;
|
|
1285
|
-
const tests = configValue.tests;
|
|
1286
|
-
console.log(`[Server_Docker] Found tests for ${runtime}:`, JSON.stringify(tests));
|
|
1287
|
-
for (const testName of tests) {
|
|
1288
|
-
const uid = `${configKey}-${testName.toLowerCase().replaceAll("/", "_").replaceAll(".", "-")}`;
|
|
1289
|
-
const bddServiceName = `${uid}-bdd`;
|
|
1290
|
-
console.log(`[Server_Docker] Starting BDD service: ${bddServiceName}, ${configKey}, ${configValue}`);
|
|
1291
|
-
try {
|
|
1292
|
-
await this.spawnPromise(`docker compose -f "testeranto/docker-compose.yml" up -d ${bddServiceName}`);
|
|
1293
|
-
this.startServiceLogging(bddServiceName, runtime).catch((error) => console.error(`[Server_Docker] Failed to start logging for ${bddServiceName}:`, error));
|
|
1294
|
-
this.captureExistingLogs(bddServiceName, runtime).catch((error) => console.error(`[Server_Docker] Failed to capture existing logs for ${bddServiceName}:`, error));
|
|
1295
|
-
} catch (error) {
|
|
1296
|
-
console.error(`[Server_Docker] Failed to start ${bddServiceName}: ${error.message}`);
|
|
1297
|
-
this.captureExistingLogs(bddServiceName, runtime).catch((err) => console.error(`[Server_Docker] Also failed to capture logs:`, err));
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
for (const [configKey, configValue] of Object.entries(this.configs)) {
|
|
1302
|
-
const runtime = configValue[0];
|
|
1303
|
-
const testsObj = configValue[3];
|
|
1304
|
-
const tests = testsObj?.tests || {};
|
|
1305
|
-
for (const testName in tests) {
|
|
1306
|
-
const uid = `${configKey}-${testName.toLowerCase().replaceAll("/", "_").replaceAll(".", "-")}`;
|
|
1307
|
-
const checks = testsObj?.checks || [];
|
|
1308
|
-
for (let i = 0; i < checks.length; i++) {
|
|
1309
|
-
const staticServiceName = `${uid}-static-${i}`;
|
|
1310
|
-
console.log(`[Server_Docker] Starting static test service: ${staticServiceName}`);
|
|
1311
|
-
try {
|
|
1312
|
-
await this.spawnPromise(`docker compose -f "testeranto/docker-compose.yml" up -d ${staticServiceName}`);
|
|
1313
|
-
this.startServiceLogging(staticServiceName, runtime).catch((error) => console.error(`[Server_Docker] Failed to start logging for ${staticServiceName}:`, error));
|
|
1314
|
-
this.captureExistingLogs(staticServiceName, runtime).catch((error) => console.error(`[Server_Docker] Failed to capture existing logs for ${staticServiceName}:`, error));
|
|
1315
|
-
} catch (error) {
|
|
1316
|
-
console.error(`[Server_Docker] Failed to start ${staticServiceName}: ${error.message}`);
|
|
1317
|
-
this.captureExistingLogs(staticServiceName, runtime).catch((err) => console.error(`[Server_Docker] Also failed to capture logs:`, err));
|
|
1318
|
-
}
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
async captureExistingLogs(serviceName, runtime) {
|
|
1324
|
-
const reportDir = path2.join(
|
|
1325
|
-
process.cwd(),
|
|
1326
|
-
"testeranto",
|
|
1327
|
-
"reports",
|
|
1328
|
-
"allTests",
|
|
1329
|
-
"example",
|
|
1330
|
-
runtime
|
|
1331
|
-
);
|
|
1332
|
-
try {
|
|
1333
|
-
fs2.mkdirSync(reportDir, { recursive: true });
|
|
1334
|
-
} catch (error) {
|
|
1335
|
-
console.error(`[Server_Docker] Failed to create report directory ${reportDir}: ${error.message}`);
|
|
1336
|
-
return;
|
|
1337
|
-
}
|
|
1338
|
-
const logFilePath = path2.join(reportDir, `${serviceName}.log`);
|
|
1339
|
-
try {
|
|
1340
|
-
const checkCmd = `docker compose -f "testeranto/docker-compose.yml" ps -a -q ${serviceName}`;
|
|
1341
|
-
const containerId = execSync(checkCmd, {
|
|
1342
|
-
// cwd: this.dockerManager.cwd,
|
|
1343
|
-
encoding: "utf-8"
|
|
1344
|
-
}).toString().trim();
|
|
1345
|
-
if (!containerId) {
|
|
1346
|
-
console.debug(`[Server_Docker] No container found for service ${serviceName}`);
|
|
1347
|
-
return;
|
|
1348
|
-
}
|
|
1349
|
-
const cmd = `docker compose -f "testeranto/docker-compose.yml" logs --no-color ${serviceName} 2>/dev/null || true`;
|
|
1350
|
-
const existingLogs = execSync(cmd, {
|
|
1351
|
-
// cwd: this.dockerManager.cwd,
|
|
1352
|
-
encoding: "utf-8",
|
|
1353
|
-
maxBuffer: 10 * 1024 * 1024
|
|
1354
|
-
// 10MB
|
|
1355
|
-
});
|
|
1356
|
-
if (existingLogs && existingLogs.trim().length > 0) {
|
|
1357
|
-
fs2.appendFileSync(logFilePath, existingLogs);
|
|
1358
|
-
console.log(`[Server_Docker] Captured ${existingLogs.length} bytes of existing logs for ${serviceName}`);
|
|
1359
|
-
}
|
|
1360
|
-
this.captureContainerExitCode(serviceName, reportDir);
|
|
1361
|
-
} catch (error) {
|
|
1362
|
-
console.debug(`[Server_Docker] No existing logs for ${serviceName}: ${error.message}`);
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
async waitForContainerHealthy(containerName, timeoutMs) {
|
|
1366
|
-
const startTime = Date.now();
|
|
1367
|
-
const checkInterval = 2e3;
|
|
1368
|
-
}
|
|
1369
|
-
async stop() {
|
|
1370
|
-
console.log(`[Server_Docker] stop()`);
|
|
1371
|
-
for (const [containerId, logProcess] of this.logProcesses.entries()) {
|
|
1372
|
-
try {
|
|
1373
|
-
logProcess.process.kill("SIGTERM");
|
|
1374
|
-
console.log(`[Server_Docker] Stopped log process for container ${containerId} (${logProcess.serviceName})`);
|
|
1375
|
-
} catch (error) {
|
|
1376
|
-
console.error(`[Server_Docker] Error stopping log process for ${containerId}:`, error);
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
this.logProcesses.clear();
|
|
1380
|
-
const result = await this.DC_down();
|
|
1381
|
-
if (result.exitCode !== 0) {
|
|
1382
|
-
console.error(`Docker Compose down failed: ${result.err}`);
|
|
1383
|
-
}
|
|
1384
|
-
super.stop();
|
|
1385
|
-
}
|
|
1386
|
-
async setupDockerCompose() {
|
|
1387
|
-
const composeDir = path2.join(process.cwd(), "testeranto", "bundles");
|
|
1388
|
-
try {
|
|
1389
|
-
fs2.mkdirSync(composeDir, { recursive: true });
|
|
1390
|
-
const services = this.generateServices(
|
|
1391
|
-
// config,
|
|
1392
|
-
);
|
|
1393
|
-
this.writeComposeFile(services);
|
|
1394
|
-
} catch (err) {
|
|
1395
|
-
console.error(`Error in setupDockerCompose:`, err);
|
|
1396
|
-
throw err;
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
writeComposeFile(services) {
|
|
1400
|
-
const dockerComposeFileContents = this.BaseCompose(services);
|
|
1401
|
-
fs2.writeFileSync(
|
|
1402
|
-
"testeranto/docker-compose.yml",
|
|
1403
|
-
yaml.dump(dockerComposeFileContents, {
|
|
1404
|
-
lineWidth: -1,
|
|
1405
|
-
noRefs: true
|
|
1406
|
-
})
|
|
1407
|
-
);
|
|
1408
|
-
}
|
|
1409
|
-
async exec(cmd, options) {
|
|
1410
|
-
const execAsync = promisify(exec);
|
|
1411
|
-
return execAsync(cmd, { cwd: options.cwd });
|
|
1412
|
-
}
|
|
1413
|
-
spawnPromise(command) {
|
|
1414
|
-
return new Promise((resolve, reject) => {
|
|
1415
|
-
console.log(`[spawnPromise] Executing: ${command}`);
|
|
1416
|
-
const child = spawn(command, {
|
|
1417
|
-
stdio: "inherit",
|
|
1418
|
-
shell: true
|
|
1419
|
-
// cwd: this.dockerManager.cwd
|
|
1420
|
-
});
|
|
1421
|
-
child.on("error", (error) => {
|
|
1422
|
-
console.error(`[spawnPromise] Failed to start process: ${error.message}`);
|
|
1423
|
-
reject(error);
|
|
1424
|
-
});
|
|
1425
|
-
child.on("close", (code) => {
|
|
1426
|
-
if (code === 0) {
|
|
1427
|
-
console.log(`[spawnPromise] Process completed successfully`);
|
|
1428
|
-
resolve(code);
|
|
1429
|
-
} else {
|
|
1430
|
-
console.error(`[spawnPromise] Process exited with code ${code}`);
|
|
1431
|
-
reject(new Error(`Process exited with code ${code}`));
|
|
1432
|
-
}
|
|
1433
|
-
});
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
async DC_upAll() {
|
|
1437
|
-
try {
|
|
1438
|
-
const cmd = this.getUpCommand();
|
|
1439
|
-
await this.spawnPromise(cmd);
|
|
1440
|
-
return {
|
|
1441
|
-
exitCode: 0,
|
|
1442
|
-
out: "",
|
|
1443
|
-
err: "",
|
|
1444
|
-
data: null
|
|
1445
|
-
};
|
|
1446
|
-
} catch (error) {
|
|
1447
|
-
console.error(
|
|
1448
|
-
`[Docker] docker compose up \u274C ${ansiColors.bgBlue(error.message.replaceAll("\\n", "\n"))}`
|
|
1449
|
-
);
|
|
1450
|
-
return {
|
|
1451
|
-
exitCode: 1,
|
|
1452
|
-
out: "",
|
|
1453
|
-
err: `Error starting services: ${error.message}`,
|
|
1454
|
-
data: null
|
|
1455
|
-
};
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
async DC_down() {
|
|
1459
|
-
try {
|
|
1460
|
-
const cmd = this.getDownCommand();
|
|
1461
|
-
await this.spawnPromise(cmd);
|
|
1462
|
-
return {
|
|
1463
|
-
exitCode: 0,
|
|
1464
|
-
out: "",
|
|
1465
|
-
err: "",
|
|
1466
|
-
data: null
|
|
1467
|
-
};
|
|
1468
|
-
} catch (error) {
|
|
1469
|
-
console.log(`[DC_down] Error during down: ${error.message}`);
|
|
1470
|
-
return {
|
|
1471
|
-
exitCode: 1,
|
|
1472
|
-
out: "",
|
|
1473
|
-
err: `Error stopping services: ${error.message}`,
|
|
1474
|
-
data: null
|
|
1475
|
-
};
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
async DC_ps() {
|
|
1479
|
-
try {
|
|
1480
|
-
const cmd = this.getPsCommand();
|
|
1481
|
-
const { stdout, stderr } = await this.exec(cmd, {
|
|
1482
|
-
// cwd: this.dockerManager.cwd
|
|
1483
|
-
});
|
|
1484
|
-
return {
|
|
1485
|
-
exitCode: 0,
|
|
1486
|
-
out: stdout,
|
|
1487
|
-
err: stderr,
|
|
1488
|
-
data: null
|
|
1489
|
-
};
|
|
1490
|
-
} catch (error) {
|
|
1491
|
-
return {
|
|
1492
|
-
exitCode: 1,
|
|
1493
|
-
out: "",
|
|
1494
|
-
err: `Error getting service status: ${error.message}`,
|
|
1495
|
-
data: null
|
|
1496
|
-
};
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
async DC_logs(serviceName, options) {
|
|
1500
|
-
const tail = options?.tail ?? 100;
|
|
1501
|
-
try {
|
|
1502
|
-
const cmd = this.getLogsCommand(serviceName, tail);
|
|
1503
|
-
const { stdout, stderr } = await this.exec(cmd, {
|
|
1504
|
-
// cwd: this.dockerManager.cwd
|
|
1505
|
-
});
|
|
1506
|
-
return {
|
|
1507
|
-
exitCode: 0,
|
|
1508
|
-
out: stdout,
|
|
1509
|
-
err: stderr,
|
|
1510
|
-
data: null
|
|
1511
|
-
};
|
|
1512
|
-
} catch (error) {
|
|
1513
|
-
return {
|
|
1514
|
-
exitCode: 1,
|
|
1515
|
-
out: "",
|
|
1516
|
-
err: `Error getting logs for ${serviceName}: ${error.message}`,
|
|
1517
|
-
data: null
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
async DC_configServices() {
|
|
1522
|
-
try {
|
|
1523
|
-
const cmd = this.getConfigServicesCommand();
|
|
1524
|
-
const { stdout, stderr } = await this.exec(cmd, {
|
|
1525
|
-
// cwd: this.dockerManager.cwd
|
|
1526
|
-
});
|
|
1527
|
-
return {
|
|
1528
|
-
exitCode: 0,
|
|
1529
|
-
out: stdout,
|
|
1530
|
-
err: stderr,
|
|
1531
|
-
data: null
|
|
1532
|
-
};
|
|
1533
|
-
} catch (error) {
|
|
1534
|
-
return {
|
|
1535
|
-
exitCode: 1,
|
|
1536
|
-
out: "",
|
|
1537
|
-
err: `Error getting services from config: ${error.message}`,
|
|
1538
|
-
data: null
|
|
1539
|
-
};
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
async DC_start() {
|
|
1543
|
-
try {
|
|
1544
|
-
const startCommand = this.getStartCommand();
|
|
1545
|
-
await this.spawnPromise(startCommand);
|
|
1546
|
-
return {
|
|
1547
|
-
exitCode: 0,
|
|
1548
|
-
data: null
|
|
1549
|
-
};
|
|
1550
|
-
} catch (error) {
|
|
1551
|
-
console.error(
|
|
1552
|
-
`[Docker] docker compose start \u274C ${ansiColors.bgBlue(error.message.replaceAll("\\n", "\n"))}`
|
|
1553
|
-
);
|
|
1554
|
-
return {
|
|
1555
|
-
exitCode: 1,
|
|
1556
|
-
data: null
|
|
1557
|
-
};
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
async DC_build() {
|
|
1561
|
-
try {
|
|
1562
|
-
const buildCommand = this.getBuildCommand();
|
|
1563
|
-
await this.spawnPromise(buildCommand);
|
|
1564
|
-
console.log(`[DC_build] Build completed successfully`);
|
|
1565
|
-
return {
|
|
1566
|
-
exitCode: 0,
|
|
1567
|
-
out: "",
|
|
1568
|
-
err: "",
|
|
1569
|
-
data: null
|
|
1570
|
-
};
|
|
1571
|
-
} catch (error) {
|
|
1572
|
-
console.error(
|
|
1573
|
-
`[Docker] docker-compose build \u274C ${ansiColors.bgBlue(error.message.replaceAll("\\n", "\n"))}`
|
|
1574
|
-
);
|
|
1575
|
-
return {
|
|
1576
|
-
exitCode: 1,
|
|
1577
|
-
out: "",
|
|
1578
|
-
err: `Error building services: ${error.message}`,
|
|
1579
|
-
data: null
|
|
1580
|
-
};
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
getProcessSummary() {
|
|
1584
|
-
console.log(`[Server_Docker] getProcessSummary called`);
|
|
1585
|
-
try {
|
|
1586
|
-
const output = execSync('docker ps --format "{{.Names}}|{{.Image}}|{{.Status}}|{{.Ports}}|{{.State}}|{{.Command}}"').toString();
|
|
1587
|
-
const processes = output.trim().split("\n").filter((line) => line.trim()).map((line) => {
|
|
1588
|
-
const parts = line.split("|");
|
|
1589
|
-
const [name, image, status, ports, state, command] = parts;
|
|
1590
|
-
let exitCode = null;
|
|
1591
|
-
try {
|
|
1592
|
-
const inspectCmd = `docker inspect --format='{{.State.ExitCode}}' ${name} 2>/dev/null || echo ""`;
|
|
1593
|
-
const exitCodeStr = execSync(inspectCmd).toString().trim();
|
|
1594
|
-
if (exitCodeStr !== "") {
|
|
1595
|
-
exitCode = parseInt(exitCodeStr, 10);
|
|
1596
|
-
if (state === "running") {
|
|
1597
|
-
exitCode = null;
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
} catch (error) {
|
|
1601
|
-
}
|
|
1602
|
-
return {
|
|
1603
|
-
processId: name,
|
|
1604
|
-
command: command || image,
|
|
1605
|
-
image,
|
|
1606
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1607
|
-
status,
|
|
1608
|
-
state,
|
|
1609
|
-
ports,
|
|
1610
|
-
exitCode,
|
|
1611
|
-
// Add additional fields that might be useful for the frontend
|
|
1612
|
-
runtime: this.getRuntimeFromName(name),
|
|
1613
|
-
health: "unknown"
|
|
1614
|
-
// We could add health check status here
|
|
1615
|
-
};
|
|
1616
|
-
});
|
|
1617
|
-
return {
|
|
1618
|
-
processes,
|
|
1619
|
-
total: processes.length,
|
|
1620
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1621
|
-
};
|
|
1622
|
-
} catch (error) {
|
|
1623
|
-
console.error(`[Server_Docker] Error getting docker processes: ${error.message}`);
|
|
1624
|
-
return {
|
|
1625
|
-
processes: [],
|
|
1626
|
-
total: 0,
|
|
1627
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1628
|
-
error: error.message
|
|
1629
|
-
};
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
getRuntimeFromName(name) {
|
|
1633
|
-
if (name.includes("node")) return "node";
|
|
1634
|
-
if (name.includes("web")) return "web";
|
|
1635
|
-
if (name.includes("golang")) return "golang";
|
|
1636
|
-
if (name.includes("python")) return "python";
|
|
1637
|
-
if (name.includes("ruby")) return "ruby";
|
|
1638
|
-
if (name.includes("browser")) return "browser";
|
|
1639
|
-
return "unknown";
|
|
1640
|
-
}
|
|
1641
|
-
};
|
|
1642
|
-
|
|
1643
|
-
// src/server/serverClasees/Server.ts
|
|
1644
|
-
console.log("hello server");
|
|
1645
|
-
readline.emitKeypressEvents(process.stdin);
|
|
1646
|
-
if (process.stdin.isTTY) process.stdin.setRawMode(true);
|
|
1647
|
-
var Server = class extends Server_Docker {
|
|
1648
|
-
constructor(configs, mode2) {
|
|
1649
|
-
super(configs, mode2);
|
|
1650
|
-
console.log("[Server] Press 'q' to initiate a graceful shutdown.");
|
|
1651
|
-
console.log("[Server] Press 'CTRL + c' to quit forcefully.");
|
|
1652
|
-
process.stdin.on("keypress", async (str, key) => {
|
|
1653
|
-
if (key.name === "q") {
|
|
1654
|
-
console.log("Testeranto is shutting down gracefully...");
|
|
1655
|
-
await this.stop();
|
|
1656
|
-
process.exit(0);
|
|
1657
|
-
}
|
|
1658
|
-
if (key.ctrl && key.name === "c") {
|
|
1659
|
-
console.log("\nForce quitting...");
|
|
1660
|
-
process.exit(1);
|
|
1661
|
-
}
|
|
1662
|
-
});
|
|
1663
|
-
process.on("SIGINT", async () => {
|
|
1664
|
-
console.log("\nForce quitting...");
|
|
1665
|
-
process.exit(1);
|
|
1666
|
-
});
|
|
1667
|
-
}
|
|
1668
|
-
async start() {
|
|
1669
|
-
console.log(`[Server] start()`);
|
|
1670
|
-
const runtimesDir = `testeranto/runtimes/`;
|
|
1671
|
-
fs3.mkdirSync(runtimesDir, { recursive: true });
|
|
1672
|
-
await super.start();
|
|
1673
|
-
}
|
|
1674
|
-
async stop() {
|
|
1675
|
-
console.log(`[Server] stop()`);
|
|
1676
|
-
await super.stop();
|
|
1677
|
-
}
|
|
1678
|
-
};
|
|
1679
|
-
|
|
1680
|
-
// src/testeranto.ts
|
|
1681
|
-
var fs4 = await import("fs/promises");
|
|
1682
|
-
var mode = process.argv[3];
|
|
1683
|
-
if (mode !== "once" && mode !== "dev") {
|
|
1684
|
-
console.error(`The 3rd argument should be 'dev' or 'once', not '${mode}'.`);
|
|
1685
|
-
process.exit(-1);
|
|
1686
|
-
}
|
|
1687
|
-
var main = async () => {
|
|
1688
|
-
const config = (await import("./testeranto-6SAYRVSE.mjs")).default;
|
|
1689
|
-
console.log("mark123", config);
|
|
1690
|
-
await new Server(config, mode).start();
|
|
1691
|
-
};
|
|
1692
|
-
main();
|