biz-a-cli 2.3.80-15296 → 2.3.80-15317
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/bin/app.js +154 -17
- package/bin/deleteApp.js +4 -3
- package/bin/directHubEvent.js +25 -25
- package/bin/hub.js +404 -352
- package/bin/hubEvent.js +713 -505
- package/bin/index.js +5 -4
- package/bin/migrate.js +289 -173
- package/bin/proxy.js +26 -25
- package/bin/script.js +125 -124
- package/bin/tunnelTarget.js +41 -0
- package/bin/uploadApp.js +6 -5
- package/bin/watcher.js +49 -63
- package/callbackController.js +65 -64
- package/config/databases.example.json +42 -0
- package/config/databases.json +20 -0
- package/config/ext-oidc.json +7 -0
- package/config/secrets.json +21 -0
- package/db/db.js +288 -43
- package/engine/bpm/bpm-agent.js +467 -385
- package/engine/bpm/routes.js +66 -61
- package/engine/bpm/workflow-runtime.js +1676 -1626
- package/engine/bpm/workflow.js +290 -283
- package/engine/domain/appConfig.js +294 -54
- package/engine/domain/applicationConfig.js +7 -7
- package/engine/domain/dialect.js +323 -0
- package/engine/domain/entityConfigLoader.js +100 -0
- package/engine/domain/firebird-ddl.js +14 -1
- package/engine/domain/postgres-ddl.js +565 -0
- package/engine/ext/token.js +8 -10
- package/engine/orm/apiRoute.js +486 -0
- package/engine/orm/changeInference.js +213 -0
- package/engine/orm/concurrency.js +132 -0
- package/engine/orm/connection.js +245 -0
- package/engine/orm/crudQuery.js +198 -0
- package/engine/orm/dataSnapShape.js +107 -0
- package/engine/orm/dialect.js +41 -0
- package/engine/orm/entityConfig.js +144 -0
- package/engine/orm/executeBlock.js +493 -0
- package/engine/orm/executor.js +285 -0
- package/engine/orm/finaAuth.js +0 -0
- package/engine/orm/finaEndpoint.js +166 -0
- package/engine/orm/imgQuery.js +82 -0
- package/engine/orm/index.js +137 -0
- package/engine/orm/joinChain.js +143 -0
- package/engine/orm/listQuery.js +164 -0
- package/engine/orm/masterDetail.js +395 -0
- package/engine/orm/registry.js +92 -0
- package/engine/orm/registryClient.js +63 -0
- package/engine/orm/userAdmin.js +98 -0
- package/logger.js +122 -0
- package/mailController.js +19 -18
- package/message-broker/agent.js +63 -62
- package/message-broker/clientEmitter.js +304 -310
- package/message-broker/dispatcher.js +161 -158
- package/message-broker/orchestrator.js +2 -2
- package/migrations/1788527682689__privileges.sql +103 -0
- package/migrations/postgres/1777727800000__config.sql +21 -0
- package/migrations/postgres/1777727810000__sys_runtime.sql +124 -0
- package/migrations/postgres/1777727873750__apps.sql +30 -0
- package/migrations/postgres/1777727892577__bpm.sql +242 -0
- package/migrations/postgres/1787137466726__ext.sql +74 -0
- package/migrations/postgres/1787201361442__ext_cli.sql +12 -0
- package/migrations/postgres/1788527682689__privileges.sql +68 -0
- package/package.json +6 -1
- package/proxyController.js +83 -82
- package/scheduler/configController.js +116 -115
- package/scheduler/datalib.js +355 -364
- package/scheduler/timer.js +88 -87
- package/scheduler/watcherController.js +94 -93
- package/security/internalPrincipal.js +134 -0
- package/security/secretProvider.js +6 -1
- package/security/tokenFormat.js +38 -0
- package/worker/cliScriptWorker.js +205 -186
- package/worker/cliWorkerPool.js +4 -1
package/bin/app.js
CHANGED
|
@@ -18,12 +18,23 @@ import { spawn } from "node:child_process";
|
|
|
18
18
|
import { newMigration, runMigrations } from "./migrate.js";
|
|
19
19
|
import {
|
|
20
20
|
APP_CONFIG_NAME,
|
|
21
|
+
buildEnsureConfigTableSql,
|
|
22
|
+
buildPostgresConfigUpsertSql,
|
|
23
|
+
buildPostgresApplicationConfigLookupSql,
|
|
24
|
+
buildPostgresSetAppSql,
|
|
21
25
|
extractConfigVersion,
|
|
22
26
|
getChunkedUpsertBlocks,
|
|
23
27
|
getUpsertBlock,
|
|
24
28
|
isSemanticVersion,
|
|
25
29
|
parseConfigForVersion,
|
|
26
30
|
} from "../engine/domain/appConfig.js";
|
|
31
|
+
import {
|
|
32
|
+
isPostgresIndex,
|
|
33
|
+
execPostgres,
|
|
34
|
+
primeRegistry,
|
|
35
|
+
} from "../engine/domain/dialect.js";
|
|
36
|
+
import { addUser } from "../engine/orm/userAdmin.js";
|
|
37
|
+
import { logger } from "../logger.js";
|
|
27
38
|
|
|
28
39
|
const getKeyFolderPath = () => {
|
|
29
40
|
const scriptPath =
|
|
@@ -511,6 +522,11 @@ async function uploadConfigs({
|
|
|
511
522
|
publish = false,
|
|
512
523
|
forceFull = false,
|
|
513
524
|
}) {
|
|
525
|
+
/* Phase B2: ask biz-a for this tenant's database coordinates before anything reads the
|
|
526
|
+
dialect. A deployed CLI has no config/databases.json, so without this the registry
|
|
527
|
+
indexes would look like Firebird. No-op when --sub is absent or biz-a is unreachable. */
|
|
528
|
+
await primeRegistry({ subdomain: sub, serverLink: env.BIZA_SERVER_LINK });
|
|
529
|
+
|
|
514
530
|
const { application, domains } = collectConfigUploads({
|
|
515
531
|
workingDir,
|
|
516
532
|
fileNames,
|
|
@@ -523,11 +539,24 @@ async function uploadConfigs({
|
|
|
523
539
|
};
|
|
524
540
|
|
|
525
541
|
const saveOne = async ({ name, version, content }) => {
|
|
542
|
+
/* A PostgreSQL index writes straight to its pool. No chunking: the block splitting below
|
|
543
|
+
exists only because the FINA HTTP body has a size limit, which a direct connection does
|
|
544
|
+
not. */
|
|
545
|
+
if (isPostgresIndex(dbIndex)) {
|
|
546
|
+
await execPostgres(buildEnsureConfigTableSql(), dbIndex);
|
|
547
|
+
await execPostgres(
|
|
548
|
+
buildPostgresConfigUpsertSql(name, version, content, false),
|
|
549
|
+
dbIndex,
|
|
550
|
+
);
|
|
551
|
+
logger.info(`saved ${name}@${version} (postgres db${dbIndex})`);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
|
|
526
555
|
const blocks = resolveUpsertBlocks(name, version, content, dbIndex);
|
|
527
556
|
for (const block of blocks) {
|
|
528
557
|
await executeConfigBlock(block, { server, apiPort, dbIndex });
|
|
529
558
|
}
|
|
530
|
-
|
|
559
|
+
logger.info(
|
|
531
560
|
`saved ${name}@${version}${blocks.length > 1 ? ` (${blocks.length} chunks)` : ""}`,
|
|
532
561
|
);
|
|
533
562
|
};
|
|
@@ -579,7 +608,7 @@ async function uploadConfigs({
|
|
|
579
608
|
`Publish ${domain.name}@${domain.version} failed: ${result?.error ?? "no error message from server"}`,
|
|
580
609
|
);
|
|
581
610
|
}
|
|
582
|
-
|
|
611
|
+
logger.info(`published ${domain.name}@${domain.version}`);
|
|
583
612
|
}
|
|
584
613
|
|
|
585
614
|
if (application) {
|
|
@@ -608,7 +637,7 @@ async function uploadConfigs({
|
|
|
608
637
|
`Publish ${application.name}@${application.version} failed: ${result?.error ?? "no error message from server"}`,
|
|
609
638
|
);
|
|
610
639
|
}
|
|
611
|
-
|
|
640
|
+
logger.info(`published ${application.name}@${application.version}`);
|
|
612
641
|
} finally {
|
|
613
642
|
process.chdir(previousCwd);
|
|
614
643
|
fs.rmSync(scratchDir, { force: true, recursive: true });
|
|
@@ -657,6 +686,22 @@ const resolveAppDisplayNameFromApplicationConfig = async ({
|
|
|
657
686
|
dbIndex,
|
|
658
687
|
sub,
|
|
659
688
|
}) => {
|
|
689
|
+
/* A PostgreSQL tenant reads SYS$CONFIG directly. This must not silently return "": the
|
|
690
|
+
display name keys the SYS$APPS row, so falling back to the random bundle name would insert
|
|
691
|
+
a fresh app row on every publish instead of updating the existing one. */
|
|
692
|
+
if (isPostgresIndex(dbIndex)) {
|
|
693
|
+
try {
|
|
694
|
+
const rows = await execPostgres(
|
|
695
|
+
buildPostgresApplicationConfigLookupSql(),
|
|
696
|
+
dbIndex,
|
|
697
|
+
);
|
|
698
|
+
const displayName = parseApplicationConfigData(rows?.[0]?.data)?.metadata?.name;
|
|
699
|
+
return typeof displayName === "string" ? displayName.trim() : "";
|
|
700
|
+
} catch {
|
|
701
|
+
return "";
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
660
705
|
if (typeof axios.request !== "function") {
|
|
661
706
|
return "";
|
|
662
707
|
}
|
|
@@ -787,7 +832,7 @@ async function addApp({
|
|
|
787
832
|
const keys = await prepareKeys();
|
|
788
833
|
if (!keys) {
|
|
789
834
|
const msg = "Can not prepare encryption keys";
|
|
790
|
-
|
|
835
|
+
logger.error(msg);
|
|
791
836
|
return { success: false, error: msg };
|
|
792
837
|
}
|
|
793
838
|
|
|
@@ -825,7 +870,7 @@ async function addApp({
|
|
|
825
870
|
}
|
|
826
871
|
const bundleFile = `${rootFolder}${bundleName}.tgz`;
|
|
827
872
|
compressIt(bundleFile, bundleFolder);
|
|
828
|
-
|
|
873
|
+
logger.info(
|
|
829
874
|
`Finished packing ${processedFile} files into "${bundleFile}" (${((performance.now() - bundlingStart) / 1000).toFixed(2)}s)`,
|
|
830
875
|
);
|
|
831
876
|
|
|
@@ -853,29 +898,44 @@ async function addApp({
|
|
|
853
898
|
const uploadAppName = normalizeAppName(
|
|
854
899
|
(useApplicationConfigName ? appDisplayName : "") || bundleName,
|
|
855
900
|
);
|
|
901
|
+
/* SYS$APPS is a Biz-A table, not a FINA one, so a PostgreSQL tenant is written
|
|
902
|
+
directly — no FINA server in the path at all. On Firebird the FINA stored
|
|
903
|
+
procedure TOrmMethod/"setApp" still owns the write. */
|
|
904
|
+
if (isPostgresIndex(dbIndex)) {
|
|
905
|
+
await execPostgres(
|
|
906
|
+
buildPostgresSetAppSql(uploadAppName, data, keys.metadata),
|
|
907
|
+
dbIndex,
|
|
908
|
+
);
|
|
909
|
+
logger.info(
|
|
910
|
+
`Finished uploading "${bundleFile}" to postgres db${dbIndex} (${((performance.now() - uploadingStart) / 1000).toFixed(2)}s)`,
|
|
911
|
+
);
|
|
912
|
+
fs.rmSync(rootFolder, { force: true, recursive: true });
|
|
913
|
+
return { success: true, data: { appName: uploadAppName } };
|
|
914
|
+
}
|
|
915
|
+
|
|
856
916
|
const param = {
|
|
857
917
|
_parameters: [dbIndex, uploadAppName, data, keys.metadata],
|
|
858
918
|
};
|
|
859
919
|
|
|
860
920
|
const res = await axios.post(url, param, { headers: headers });
|
|
861
921
|
if (res.data.success) {
|
|
862
|
-
|
|
922
|
+
logger.info(
|
|
863
923
|
`Finished uploading "${bundleFile}" (${((performance.now() - uploadingStart) / 1000).toFixed(2)}s)`,
|
|
864
924
|
);
|
|
865
925
|
fs.rmSync(rootFolder, { force: true, recursive: true });
|
|
866
926
|
return { success: true, data: res.data };
|
|
867
927
|
}
|
|
868
928
|
|
|
869
|
-
|
|
929
|
+
logger.error(res.data.error);
|
|
870
930
|
return { success: false, error: res.data.error, data: res.data };
|
|
871
931
|
}
|
|
872
932
|
|
|
873
933
|
const msg = "Nothing to upload. Please recheck your app folder.";
|
|
874
|
-
|
|
934
|
+
logger.error(msg);
|
|
875
935
|
return { success: false, error: msg };
|
|
876
936
|
} catch (e) {
|
|
877
937
|
const errMsg = e.response?.data ? e.response.data : e;
|
|
878
|
-
|
|
938
|
+
logger.error(errMsg);
|
|
879
939
|
return { success: false, error: errMsg };
|
|
880
940
|
} finally {
|
|
881
941
|
process.chdir(oldCwd);
|
|
@@ -914,9 +974,9 @@ async function runUnitTests(options) {
|
|
|
914
974
|
});
|
|
915
975
|
|
|
916
976
|
child.on("close", async (code) => {
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
977
|
+
logger.info("====================");
|
|
978
|
+
logger.info(output);
|
|
979
|
+
logger.info("====================");
|
|
920
980
|
const noTestsFound = output.includes("No tests found");
|
|
921
981
|
const missingJest =
|
|
922
982
|
output.includes("missing packages") && output.includes("jest");
|
|
@@ -939,7 +999,7 @@ async function runUnitTests(options) {
|
|
|
939
999
|
forceFull: options.forceFull,
|
|
940
1000
|
});
|
|
941
1001
|
} else {
|
|
942
|
-
|
|
1002
|
+
logger.error("Biz-A Add aborted");
|
|
943
1003
|
}
|
|
944
1004
|
resolve();
|
|
945
1005
|
});
|
|
@@ -999,7 +1059,7 @@ const buildCli = () =>
|
|
|
999
1059
|
});
|
|
1000
1060
|
if (res.data?.success) {
|
|
1001
1061
|
if (deleteApps == "") {
|
|
1002
|
-
|
|
1062
|
+
logger.info("All apps removed");
|
|
1003
1063
|
} else {
|
|
1004
1064
|
const failedList =
|
|
1005
1065
|
res.data._f &&
|
|
@@ -1012,18 +1072,18 @@ const buildCli = () =>
|
|
|
1012
1072
|
: [];
|
|
1013
1073
|
const removeList = deleteApps.split(",");
|
|
1014
1074
|
removeList.forEach((app) => {
|
|
1015
|
-
|
|
1075
|
+
logger.info(
|
|
1016
1076
|
`${app} ${failedList.indexOf(app) == -1 ? "removed" : "not found"}`,
|
|
1017
1077
|
);
|
|
1018
1078
|
});
|
|
1019
1079
|
}
|
|
1020
1080
|
} else {
|
|
1021
|
-
|
|
1081
|
+
logger.error(res.data.error);
|
|
1022
1082
|
}
|
|
1023
1083
|
return res;
|
|
1024
1084
|
} catch (e) {
|
|
1025
1085
|
const errMsg = e.response?.data ? e.response.data : e;
|
|
1026
|
-
|
|
1086
|
+
logger.error(errMsg);
|
|
1027
1087
|
return errMsg;
|
|
1028
1088
|
}
|
|
1029
1089
|
})();
|
|
@@ -1043,6 +1103,83 @@ const buildCli = () =>
|
|
|
1043
1103
|
},
|
|
1044
1104
|
(commandOptions) => newMigration(commandOptions),
|
|
1045
1105
|
)
|
|
1106
|
+
.command(
|
|
1107
|
+
"user:add",
|
|
1108
|
+
"Create a platform user in SYS$USERS on a PostgreSQL tenant (defaults: supervisor/supervisor)",
|
|
1109
|
+
(yargs) =>
|
|
1110
|
+
yargs
|
|
1111
|
+
.option("u", {
|
|
1112
|
+
alias: "username",
|
|
1113
|
+
describe: "User name (stored upper-cased, as the login expects)",
|
|
1114
|
+
type: "string",
|
|
1115
|
+
default: "supervisor",
|
|
1116
|
+
})
|
|
1117
|
+
.option("w", {
|
|
1118
|
+
alias: "password",
|
|
1119
|
+
describe: "Password. Hashed with scrypt before it is stored",
|
|
1120
|
+
type: "string",
|
|
1121
|
+
default: "supervisor",
|
|
1122
|
+
})
|
|
1123
|
+
.option("fullname", {
|
|
1124
|
+
describe: "Display name (defaults to the user name)",
|
|
1125
|
+
type: "string",
|
|
1126
|
+
})
|
|
1127
|
+
.option("userlevel", {
|
|
1128
|
+
describe: "User level. Anything below 0 cannot log in",
|
|
1129
|
+
type: "number",
|
|
1130
|
+
default: 9,
|
|
1131
|
+
})
|
|
1132
|
+
.option("replace", {
|
|
1133
|
+
describe:
|
|
1134
|
+
"Reset the password if the user already exists. Without it an existing user is left untouched",
|
|
1135
|
+
type: "boolean",
|
|
1136
|
+
default: false,
|
|
1137
|
+
})
|
|
1138
|
+
.option("admin", {
|
|
1139
|
+
describe:
|
|
1140
|
+
"Grant admin (SYS$ADMINISTRATOR). The FIRST user is granted automatically - without one, nobody can reach the admin screens or publish",
|
|
1141
|
+
type: "boolean",
|
|
1142
|
+
default: false,
|
|
1143
|
+
}),
|
|
1144
|
+
async (commandOptions) => {
|
|
1145
|
+
const dbIndex = Number(commandOptions.dbIndex);
|
|
1146
|
+
try {
|
|
1147
|
+
await primeRegistry({
|
|
1148
|
+
subdomain: commandOptions.sub,
|
|
1149
|
+
serverLink: env.BIZA_SERVER_LINK,
|
|
1150
|
+
});
|
|
1151
|
+
const result = await addUser(
|
|
1152
|
+
{
|
|
1153
|
+
username: commandOptions.username,
|
|
1154
|
+
password: commandOptions.password,
|
|
1155
|
+
fullname: commandOptions.fullname,
|
|
1156
|
+
userlevel: commandOptions.userlevel,
|
|
1157
|
+
replace: commandOptions.replace,
|
|
1158
|
+
admin: commandOptions.admin,
|
|
1159
|
+
},
|
|
1160
|
+
{
|
|
1161
|
+
exec: execPostgres,
|
|
1162
|
+
dbIndex,
|
|
1163
|
+
isPostgres: isPostgresIndex(dbIndex),
|
|
1164
|
+
},
|
|
1165
|
+
);
|
|
1166
|
+
if (result.status === "exists") {
|
|
1167
|
+
logger.info(
|
|
1168
|
+
`user ${result.username} already exists in db${dbIndex} - password left untouched. Use --replace to reset it.` +
|
|
1169
|
+
(result.admin ? " Granted admin." : ""),
|
|
1170
|
+
);
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
logger.info(
|
|
1174
|
+
`user ${result.username} ${result.status} in db${dbIndex}` +
|
|
1175
|
+
(result.admin ? " and granted admin" : ""),
|
|
1176
|
+
);
|
|
1177
|
+
} catch (error) {
|
|
1178
|
+
logger.error(`user:add failed: ${error?.message ?? error}`);
|
|
1179
|
+
process.exitCode = 1;
|
|
1180
|
+
}
|
|
1181
|
+
},
|
|
1182
|
+
)
|
|
1046
1183
|
.command(
|
|
1047
1184
|
"migrate:run",
|
|
1048
1185
|
"Run pending DDL migrations from the /migrations folder",
|
package/bin/deleteApp.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import yargs from "yargs";
|
|
4
4
|
import axios from "axios";
|
|
5
|
+
import { logger } from "../logger.js";
|
|
5
6
|
import { env } from "../envs/env.js"
|
|
6
7
|
|
|
7
8
|
const options = yargs(process.argv.slice(2))
|
|
@@ -52,12 +53,12 @@ const deleteApp = async () => {
|
|
|
52
53
|
const param = { _parameters: [options.dbindex, deleteApps] }
|
|
53
54
|
const res = await axios.post(url, param, { headers: headers });
|
|
54
55
|
if (res.data.success) {
|
|
55
|
-
|
|
56
|
+
logger.info(`${deleteApps=='' ? 'All' : deleteApps} apps removed`)
|
|
56
57
|
} else {
|
|
57
|
-
|
|
58
|
+
logger.error(res.data.error)
|
|
58
59
|
}
|
|
59
60
|
} catch (e) {
|
|
60
|
-
|
|
61
|
+
logger.error(e.response?.data ? e.response.data : e)
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
64
|
|
package/bin/directHubEvent.js
CHANGED
|
@@ -6,6 +6,9 @@ import { CLIENT_ROOM } from "../message-broker/clientEmitter.js";
|
|
|
6
6
|
import { ClientEmitter } from "../message-broker/clientEmitter.js";
|
|
7
7
|
import { joinExtRooms } from "../engine/ext/esb.js";
|
|
8
8
|
import { extClientListener } from "../engine/ext/socketListener.js";
|
|
9
|
+
import { prefixedLogger } from "../logger.js";
|
|
10
|
+
|
|
11
|
+
const logger = prefixedLogger("[DirectHub]");
|
|
9
12
|
|
|
10
13
|
export async function localhostTunnel(port, notifier) {
|
|
11
14
|
let tunnelUrl = "";
|
|
@@ -16,55 +19,52 @@ export async function localhostTunnel(port, notifier) {
|
|
|
16
19
|
}, RECONNECT_SOCKET_DELAY);
|
|
17
20
|
}
|
|
18
21
|
qt.on("url", (qtUrl) => {
|
|
19
|
-
// console.log('qt url', qtUrl)
|
|
20
22
|
tunnelUrl = qtUrl;
|
|
21
23
|
})
|
|
22
24
|
.on("connected", (conn) => {
|
|
23
|
-
// console.log('qt connect', conn)
|
|
24
25
|
notifier(tunnelUrl);
|
|
25
|
-
|
|
26
|
-
`${new Date()}: Connected to Direct Hub at public URL ${tunnelUrl}`,
|
|
27
|
-
);
|
|
26
|
+
logger.info(`Connected to Direct Hub at public URL ${tunnelUrl}`);
|
|
28
27
|
})
|
|
29
28
|
.on("disconnected", (conn) => {
|
|
30
|
-
// console.log('qt disconnect', conn)
|
|
31
29
|
notifier("");
|
|
32
30
|
qt.stop();
|
|
31
|
+
logger.info(
|
|
32
|
+
`Disconnected from edge node. Awaiting native reconnect...`,
|
|
33
|
+
);
|
|
33
34
|
})
|
|
34
35
|
.on("error", (err) => {
|
|
35
|
-
// console.log('qt err', err)
|
|
36
36
|
notifier("");
|
|
37
37
|
qt.stop();
|
|
38
|
+
logger.error(
|
|
39
|
+
`Tunnel error: ${err.message || err}. Awaiting native reconnect...`,
|
|
40
|
+
);
|
|
38
41
|
})
|
|
39
42
|
.on("exit", (code) => {
|
|
40
|
-
// console.log('qt exit', code)
|
|
41
43
|
notifier("");
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
logger.error(
|
|
45
|
+
`Direct Hub is not available, will try to reinitiate it in ${RECONNECT_SOCKET_DELAY / 1000} seconds. Error code : `,
|
|
44
46
|
code,
|
|
45
47
|
);
|
|
46
48
|
reconnectTunnel();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
})
|
|
50
|
+
.on("stdout", (data) => {
|
|
51
|
+
logger.debug(`stdout`, data);
|
|
52
|
+
})
|
|
53
|
+
.on("stderr", (data) => {
|
|
54
|
+
logger.debug(`stderr`, data);
|
|
53
55
|
});
|
|
56
|
+
|
|
54
57
|
return qt;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
export function directHubEvent(serverSocket, argv) {
|
|
58
61
|
serverSocket.on("connection", (clientSocket) => {
|
|
59
62
|
const setConnectListeners = (sock) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
console.log(id, `disconnected. Reason : ${reason}`);
|
|
66
|
-
});
|
|
67
|
-
}
|
|
63
|
+
const id = `<${sock.handshake?.query?.isClient ? `Client` : sock.handshake?.query?.isDeploy ? "Deployer" : sock.handshake?.query?.isLoopback ? "DirectHub Heartbeat" : "Anonymous"}> ${sock.id}`;
|
|
64
|
+
logger.debug(id, `connected`);
|
|
65
|
+
sock.on("disconnect", (reason) => {
|
|
66
|
+
logger.debug(id, `disconnected. Reason : ${reason}`);
|
|
67
|
+
});
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
if (clientSocket.handshake.query.isClient) {
|
|
@@ -81,7 +81,7 @@ export function directHubEvent(serverSocket, argv) {
|
|
|
81
81
|
joinExtRooms(clientSocket, extToken, { slug: extSlug });
|
|
82
82
|
} else {
|
|
83
83
|
// INTERNAL client — full listener + existing rooms, unchanged.
|
|
84
|
-
clientListener(clientSocket, argv);
|
|
84
|
+
clientListener(clientSocket, argv, "direct");
|
|
85
85
|
clientSocket.join(CLIENT_ROOM);
|
|
86
86
|
|
|
87
87
|
// isolated Client in a room using clientInstanceId
|