agl 1.0.17 → 21.0.2
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/.smartconfig.json +55 -0
- package/changelog.md +1026 -0
- package/cli.js +14 -0
- package/dist_serve/bundle.js +44778 -0
- package/dist_serve/index.html +13 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.authmodels.d.ts +126 -0
- package/dist_ts/classes.authmodels.js +1422 -0
- package/dist_ts/classes.authstore.d.ts +160 -0
- package/dist_ts/classes.authstore.js +2483 -0
- package/dist_ts/classes.browserresourcehost.d.ts +85 -0
- package/dist_ts/classes.browserresourcehost.js +912 -0
- package/dist_ts/classes.cli.d.ts +21 -0
- package/dist_ts/classes.cli.js +1082 -0
- package/dist_ts/classes.config.d.ts +23 -0
- package/dist_ts/classes.config.js +267 -0
- package/dist_ts/classes.controller.d.ts +523 -0
- package/dist_ts/classes.controller.js +10611 -0
- package/dist_ts/classes.controllermanagement.d.ts +32 -0
- package/dist_ts/classes.controllermanagement.js +222 -0
- package/dist_ts/classes.draftmanager.d.ts +30 -0
- package/dist_ts/classes.draftmanager.js +179 -0
- package/dist_ts/classes.embeddeddb.d.ts +30 -0
- package/dist_ts/classes.embeddeddb.js +159 -0
- package/dist_ts/classes.flexframedtransport.d.ts +56 -0
- package/dist_ts/classes.flexframedtransport.js +275 -0
- package/dist_ts/classes.flexmodels.private.d.ts +231 -0
- package/dist_ts/classes.flexmodels.private.js +985 -0
- package/dist_ts/classes.flexmodels.public.d.ts +207 -0
- package/dist_ts/classes.flexmodels.public.js +885 -0
- package/dist_ts/classes.flexprojectionreader.d.ts +89 -0
- package/dist_ts/classes.flexprojectionreader.js +580 -0
- package/dist_ts/classes.flexservice.d.ts +196 -0
- package/dist_ts/classes.flexservice.js +3704 -0
- package/dist_ts/classes.flexstore.d.ts +174 -0
- package/dist_ts/classes.flexstore.js +3400 -0
- package/dist_ts/classes.flexsupervisor.d.ts +105 -0
- package/dist_ts/classes.flexsupervisor.js +1191 -0
- package/dist_ts/classes.gitreversion.d.ts +431 -0
- package/dist_ts/classes.gitreversion.js +10592 -0
- package/dist_ts/classes.harnessoperationmanager.d.ts +113 -0
- package/dist_ts/classes.harnessoperationmanager.js +602 -0
- package/dist_ts/classes.opencodeclient.d.ts +146 -0
- package/dist_ts/classes.opencodeclient.js +3003 -0
- package/dist_ts/classes.opencodesupervisor.d.ts +60 -0
- package/dist_ts/classes.opencodesupervisor.js +1003 -0
- package/dist_ts/classes.passkeymanager.d.ts +34 -0
- package/dist_ts/classes.passkeymanager.js +456 -0
- package/dist_ts/classes.processinspection.d.ts +50 -0
- package/dist_ts/classes.processinspection.js +484 -0
- package/dist_ts/classes.resourcecoordinator.d.ts +64 -0
- package/dist_ts/classes.resourcecoordinator.js +294 -0
- package/dist_ts/classes.sessionintelligencereader.d.ts +13 -0
- package/dist_ts/classes.sessionintelligencereader.js +40 -0
- package/dist_ts/classes.systemmetricssampler.d.ts +53 -0
- package/dist_ts/classes.systemmetricssampler.js +168 -0
- package/dist_ts/classes.terminalmanager.d.ts +95 -0
- package/dist_ts/classes.terminalmanager.js +981 -0
- package/dist_ts/classes.terminalresourcehost.d.ts +20 -0
- package/dist_ts/classes.terminalresourcehost.js +84 -0
- package/dist_ts/classes.upgradecoordinator.d.ts +244 -0
- package/dist_ts/classes.upgradecoordinator.js +2155 -0
- package/dist_ts/classes.upgradetransaction.d.ts +92 -0
- package/dist_ts/classes.upgradetransaction.js +2125 -0
- package/dist_ts/classes.uploadmanager.d.ts +24 -0
- package/dist_ts/classes.uploadmanager.js +210 -0
- package/dist_ts/classes.validation.d.ts +91 -0
- package/dist_ts/classes.validation.js +1087 -0
- package/dist_ts/flexharness.child.d.ts +1 -0
- package/dist_ts/flexharness.child.js +28 -0
- package/dist_ts/functions.canonicaldirectory.d.ts +21 -0
- package/dist_ts/functions.canonicaldirectory.js +144 -0
- package/dist_ts/functions.controllerdataroot.d.ts +15 -0
- package/dist_ts/functions.controllerdataroot.js +76 -0
- package/dist_ts/functions.embeddeddb.d.ts +2 -0
- package/dist_ts/functions.embeddeddb.js +21 -0
- package/dist_ts/functions.flexcredentialstore.d.ts +16 -0
- package/dist_ts/functions.flexcredentialstore.js +93 -0
- package/dist_ts/functions.opencodeauth.d.ts +3 -0
- package/dist_ts/functions.opencodeauth.js +31 -0
- package/dist_ts/functions.runtimeenvironment.d.ts +2 -0
- package/dist_ts/functions.runtimeenvironment.js +79 -0
- package/dist_ts/functions.upgradefollower.d.ts +3 -0
- package/dist_ts/functions.upgradefollower.js +95 -0
- package/dist_ts/index.d.ts +24 -0
- package/dist_ts/index.js +25 -0
- package/dist_ts/interfaces.auth.d.ts +181 -0
- package/dist_ts/interfaces.auth.js +82 -0
- package/dist_ts/interfaces.config.d.ts +34 -0
- package/dist_ts/interfaces.config.js +2 -0
- package/dist_ts/interfaces.flexipc.d.ts +939 -0
- package/dist_ts/interfaces.flexipc.js +1492 -0
- package/dist_ts/interfaces.gitreversion.d.ts +246 -0
- package/dist_ts/interfaces.gitreversion.js +2 -0
- package/dist_ts/interfaces.lifecycle.d.ts +37 -0
- package/dist_ts/interfaces.lifecycle.js +2 -0
- package/dist_ts/interfaces.opencode.d.ts +101 -0
- package/dist_ts/interfaces.opencode.js +3 -0
- package/dist_ts/interfaces.projects.d.ts +156 -0
- package/dist_ts/interfaces.projects.js +5 -0
- package/dist_ts/plugins.d.ts +36 -0
- package/dist_ts/plugins.js +40 -0
- package/dist_ts_interfaces/index.d.ts +2 -0
- package/dist_ts_interfaces/index.js +3 -0
- package/dist_ts_interfaces/interfaces.d.ts +747 -0
- package/dist_ts_interfaces/interfaces.js +47 -0
- package/dist_ts_interfaces/plugins.d.ts +4 -0
- package/dist_ts_interfaces/plugins.js +3 -0
- package/dist_ts_interfaces/requests.d.ts +806 -0
- package/dist_ts_interfaces/requests.js +2 -0
- package/dist_ts_migration/classes.documentmigrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.documentmigrationrunner.js +24 -0
- package/dist_ts_migration/classes.flexmigrationrunner.d.ts +11 -0
- package/dist_ts_migration/classes.flexmigrationrunner.js +25 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.d.ts +10 -0
- package/dist_ts_migration/classes.flexpostharnessmigrationrunner.js +15 -0
- package/dist_ts_migration/classes.migrationrunner.d.ts +8 -0
- package/dist_ts_migration/classes.migrationrunner.js +34 -0
- package/dist_ts_migration/index.d.ts +12 -0
- package/dist_ts_migration/index.js +13 -0
- package/dist_ts_migration/v10_flexharnessv3migration.d.ts +11 -0
- package/dist_ts_migration/v10_flexharnessv3migration.js +23 -0
- package/dist_ts_migration/v13_flexprojectionorder.d.ts +11 -0
- package/dist_ts_migration/v13_flexprojectionorder.js +23 -0
- package/dist_ts_migration/v16_flexprovidercredentials.d.ts +22 -0
- package/dist_ts_migration/v16_flexprovidercredentials.js +149 -0
- package/dist_ts_migration/v18_resourcelayout.d.ts +22 -0
- package/dist_ts_migration/v18_resourcelayout.js +23 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.d.ts +6 -0
- package/dist_ts_migration/v18_resourcelayoutmigration.js +61 -0
- package/dist_ts_migration/v19_flexprojectmanagement.d.ts +11 -0
- package/dist_ts_migration/v19_flexprojectmanagement.js +21 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.d.ts +28 -0
- package/dist_ts_migration/v1_embeddeddatabaselocation.js +415 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.d.ts +7 -0
- package/dist_ts_migration/v22_projectfilesystemidentitymigration.js +105 -0
- package/dist_ts_migration/v2_controllerdataroot.d.ts +130 -0
- package/dist_ts_migration/v2_controllerdataroot.js +1887 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocumentmigration.js +100 -0
- package/dist_ts_migration/v6_protocoldocuments.d.ts +7 -0
- package/dist_ts_migration/v6_protocoldocuments.js +138 -0
- package/html/index.html +13 -0
- package/{LICENSE → license.md} +2 -2
- package/package.json +86 -48
- package/readme.md +480 -0
- package/readme.plan.md +188 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.authmodels.ts +1245 -0
- package/ts/classes.authstore.ts +3274 -0
- package/ts/classes.browserresourcehost.ts +1205 -0
- package/ts/classes.cli.ts +1254 -0
- package/ts/classes.config.ts +351 -0
- package/ts/classes.controller.ts +14426 -0
- package/ts/classes.controllermanagement.ts +330 -0
- package/ts/classes.draftmanager.ts +232 -0
- package/ts/classes.embeddeddb.ts +166 -0
- package/ts/classes.flexframedtransport.ts +283 -0
- package/ts/classes.flexmodels.private.ts +823 -0
- package/ts/classes.flexmodels.public.ts +732 -0
- package/ts/classes.flexprojectionreader.ts +816 -0
- package/ts/classes.flexservice.ts +4302 -0
- package/ts/classes.flexstore.ts +4565 -0
- package/ts/classes.flexsupervisor.ts +1453 -0
- package/ts/classes.gitreversion.ts +13353 -0
- package/ts/classes.harnessoperationmanager.ts +870 -0
- package/ts/classes.opencodeclient.ts +4110 -0
- package/ts/classes.opencodesupervisor.ts +1280 -0
- package/ts/classes.passkeymanager.ts +570 -0
- package/ts/classes.processinspection.ts +623 -0
- package/ts/classes.resourcecoordinator.ts +436 -0
- package/ts/classes.sessionintelligencereader.ts +52 -0
- package/ts/classes.systemmetricssampler.ts +215 -0
- package/ts/classes.terminalmanager.ts +1207 -0
- package/ts/classes.terminalresourcehost.ts +122 -0
- package/ts/classes.upgradecoordinator.ts +2675 -0
- package/ts/classes.upgradetransaction.ts +2900 -0
- package/ts/classes.uploadmanager.ts +240 -0
- package/ts/classes.validation.ts +1409 -0
- package/ts/flexharness.child.ts +35 -0
- package/ts/functions.canonicaldirectory.ts +213 -0
- package/ts/functions.controllerdataroot.ts +107 -0
- package/ts/functions.embeddeddb.ts +22 -0
- package/ts/functions.flexcredentialstore.ts +128 -0
- package/ts/functions.opencodeauth.ts +34 -0
- package/ts/functions.runtimeenvironment.ts +90 -0
- package/ts/functions.upgradefollower.ts +115 -0
- package/ts/index.ts +36 -6
- package/ts/interfaces.auth.ts +316 -0
- package/ts/interfaces.config.ts +37 -0
- package/ts/interfaces.flexipc.ts +2586 -0
- package/ts/interfaces.gitreversion.ts +336 -0
- package/ts/interfaces.lifecycle.ts +46 -0
- package/ts/interfaces.opencode.ts +153 -0
- package/ts/interfaces.projects.ts +182 -0
- package/ts/plugins.ts +64 -0
- package/ts_interfaces/index.ts +2 -0
- package/ts_interfaces/interfaces.ts +827 -0
- package/ts_interfaces/plugins.ts +15 -0
- package/ts_interfaces/requests.ts +1186 -0
- package/ts_migration/classes.documentmigrationrunner.ts +32 -0
- package/ts_migration/classes.flexmigrationrunner.ts +33 -0
- package/ts_migration/classes.flexpostharnessmigrationrunner.ts +22 -0
- package/ts_migration/classes.migrationrunner.ts +40 -0
- package/ts_migration/index.ts +12 -0
- package/ts_migration/v10_flexharnessv3migration.ts +35 -0
- package/ts_migration/v13_flexprojectionorder.ts +33 -0
- package/ts_migration/v16_flexprovidercredentials.ts +196 -0
- package/ts_migration/v18_resourcelayout.ts +55 -0
- package/ts_migration/v18_resourcelayoutmigration.ts +68 -0
- package/ts_migration/v19_flexprojectmanagement.ts +28 -0
- package/ts_migration/v1_embeddeddatabaselocation.ts +560 -0
- package/ts_migration/v22_projectfilesystemidentitymigration.ts +121 -0
- package/ts_migration/v2_controllerdataroot.ts +2349 -0
- package/ts_migration/v6_protocoldocumentmigration.ts +144 -0
- package/ts_migration/v6_protocoldocuments.ts +198 -0
- package/ts_web/00_commitinfo_data.ts +8 -0
- package/ts_web/classes.controllersocketclient.ts +517 -0
- package/ts_web/classes.sessiondraftsync.ts +390 -0
- package/ts_web/elements.harnesscontrollerapp.ts +11494 -0
- package/ts_web/index.ts +2 -0
- package/ts_web/plugins.ts +31 -0
- package/.gitlab-ci.yml +0 -71
- package/.npmignore +0 -5
- package/README.md +0 -40
- package/dist/cli.js +0 -2
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -9
- package/dist/mod_bundle/index.d.ts +0 -1
- package/dist/mod_bundle/index.js +0 -18
- package/dist/mod_bundle/mod.plugins.d.ts +0 -4
- package/dist/mod_bundle/mod.plugins.js +0 -11
- package/dist/mod_install/index.d.ts +0 -4
- package/dist/mod_install/index.js +0 -21
- package/dist/mod_install/mod.plugins.d.ts +0 -1
- package/dist/mod_install/mod.plugins.js +0 -7
- package/dist/mod_standard/index.d.ts +0 -4
- package/dist/mod_standard/index.js +0 -21
- package/dist/mod_standard/mod.browser.d.ts +0 -6
- package/dist/mod_standard/mod.browser.js +0 -14
- package/dist/mod_standard/mod.clean.d.ts +0 -4
- package/dist/mod_standard/mod.clean.js +0 -12
- package/dist/mod_standard/mod.compile.d.ts +0 -4
- package/dist/mod_standard/mod.compile.js +0 -21
- package/dist/mod_standard/mod.plugins.d.ts +0 -8
- package/dist/mod_standard/mod.plugins.js +0 -19
- package/dist/mod_standard/mod.test.d.ts +0 -4
- package/dist/mod_standard/mod.test.js +0 -12
- package/dist/plr.cli.d.ts +0 -3
- package/dist/plr.cli.js +0 -57
- package/dist/plr.config.d.ts +0 -11
- package/dist/plr.config.js +0 -26
- package/dist/plr.mods.d.ts +0 -17
- package/dist/plr.mods.js +0 -17
- package/dist/plr.paths.d.ts +0 -19
- package/dist/plr.paths.js +0 -26
- package/dist/plr.plugins.d.ts +0 -8
- package/dist/plr.plugins.js +0 -16
- package/npmextra.json +0 -10
- package/ts/mod_bundle/index.ts +0 -20
- package/ts/mod_bundle/mod.plugins.ts +0 -9
- package/ts/mod_install/index.ts +0 -20
- package/ts/mod_install/mod.plugins.ts +0 -1
- package/ts/mod_standard/index.ts +0 -23
- package/ts/mod_standard/mod.browser.ts +0 -17
- package/ts/mod_standard/mod.clean.ts +0 -13
- package/ts/mod_standard/mod.compile.ts +0 -23
- package/ts/mod_standard/mod.plugins.ts +0 -17
- package/ts/mod_standard/mod.test.ts +0 -13
- package/ts/plr.cli.ts +0 -60
- package/ts/plr.config.ts +0 -36
- package/ts/plr.mods.ts +0 -25
- package/ts/plr.paths.ts +0 -29
- package/ts/plr.plugins.ts +0 -17
- package/tslint.json +0 -3
- package/yarn.lock +0 -3464
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { controllerPackageName } from '../dist_ts_interfaces/index.js';
|
|
3
|
+
import { defaultControllerPort } from './classes.config.js';
|
|
4
|
+
const maximumProcessIdentities = 16_384;
|
|
5
|
+
const processIdentityBatchSize = 128;
|
|
6
|
+
const maximumProcessArguments = 512;
|
|
7
|
+
const maximumProcessArgumentBytes = 256 * 1024;
|
|
8
|
+
const maximumProcessCommandBytes = maximumProcessArgumentBytes + maximumProcessArguments;
|
|
9
|
+
const maximumReconstructedPathArguments = 32;
|
|
10
|
+
const maximumDataWriterCliPaths = 8;
|
|
11
|
+
const maximumDataWriterCandidates = 1_024;
|
|
12
|
+
const currentRuntimeName = String(controllerPackageName) === 'agl' ? 'AGL' : 'hcon';
|
|
13
|
+
const installedControllerPackagePaths = [
|
|
14
|
+
plugins.path.join('node_modules', '@modelprofile.com', 'harness-controller'),
|
|
15
|
+
plugins.path.join('node_modules', 'agl'),
|
|
16
|
+
];
|
|
17
|
+
const boundedProcessArgumentsPrefix = (argumentsArg) => {
|
|
18
|
+
const bounded = [];
|
|
19
|
+
let totalBytes = 0;
|
|
20
|
+
for (const argument of argumentsArg) {
|
|
21
|
+
const argumentBytes = Buffer.byteLength(argument, 'utf8');
|
|
22
|
+
if (bounded.length >= maximumProcessArguments
|
|
23
|
+
|| totalBytes + argumentBytes > maximumProcessArgumentBytes)
|
|
24
|
+
break;
|
|
25
|
+
bounded.push(argument);
|
|
26
|
+
totalBytes += argumentBytes;
|
|
27
|
+
}
|
|
28
|
+
return bounded;
|
|
29
|
+
};
|
|
30
|
+
const assertPid = (pidArg) => {
|
|
31
|
+
if (!Number.isSafeInteger(pidArg) || pidArg < 2) {
|
|
32
|
+
throw new Error('Controller PID is invalid.');
|
|
33
|
+
}
|
|
34
|
+
return pidArg;
|
|
35
|
+
};
|
|
36
|
+
const execFile = async (fileArg, argsArg, optionsArg = {}) => {
|
|
37
|
+
return await new Promise((resolve, reject) => {
|
|
38
|
+
plugins.childProcess.execFile(fileArg, argsArg, {
|
|
39
|
+
encoding: 'utf8',
|
|
40
|
+
maxBuffer: optionsArg.maxBufferBytes ?? 128 * 1024,
|
|
41
|
+
timeout: optionsArg.timeoutMs ?? 2_000,
|
|
42
|
+
killSignal: 'SIGKILL',
|
|
43
|
+
...(optionsArg.detached === undefined ? {} : { detached: optionsArg.detached }),
|
|
44
|
+
}, (errorArg, stdoutArg) => {
|
|
45
|
+
if (errorArg) {
|
|
46
|
+
reject(errorArg);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
resolve(stdoutArg);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const readBoundedLinuxCommandArguments = async (pidArg) => {
|
|
54
|
+
// Read only the accepted argv budget plus one byte so oversized processes
|
|
55
|
+
// cannot make a system-wide inventory retain unbounded command data.
|
|
56
|
+
const handle = await plugins.fs.promises.open(`/proc/${pidArg}/cmdline`, plugins.fs.constants.O_RDONLY);
|
|
57
|
+
try {
|
|
58
|
+
const buffer = Buffer.allocUnsafe(maximumProcessCommandBytes + 1);
|
|
59
|
+
let bytesRead = 0;
|
|
60
|
+
while (bytesRead < buffer.length) {
|
|
61
|
+
const read = await handle.read(buffer, bytesRead, buffer.length - bytesRead, null);
|
|
62
|
+
if (read.bytesRead === 0)
|
|
63
|
+
break;
|
|
64
|
+
bytesRead += read.bytesRead;
|
|
65
|
+
}
|
|
66
|
+
const commandLength = Math.min(bytesRead, maximumProcessCommandBytes);
|
|
67
|
+
const argumentsResult = [];
|
|
68
|
+
let argumentStart = 0;
|
|
69
|
+
let argumentCountExceeded = false;
|
|
70
|
+
for (let index = 0; index < commandLength; index++) {
|
|
71
|
+
if (buffer[index] !== 0)
|
|
72
|
+
continue;
|
|
73
|
+
if (argumentsResult.length >= maximumProcessArguments) {
|
|
74
|
+
argumentCountExceeded = true;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
if (index > argumentStart) {
|
|
78
|
+
argumentsResult.push(buffer.subarray(argumentStart, index).toString('utf8'));
|
|
79
|
+
}
|
|
80
|
+
argumentStart = index + 1;
|
|
81
|
+
}
|
|
82
|
+
if (bytesRead <= maximumProcessCommandBytes
|
|
83
|
+
&& !argumentCountExceeded
|
|
84
|
+
&& argumentStart < commandLength
|
|
85
|
+
&& argumentsResult.length < maximumProcessArguments) {
|
|
86
|
+
argumentsResult.push(buffer.subarray(argumentStart, commandLength).toString('utf8'));
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
arguments: argumentsResult,
|
|
90
|
+
truncated: bytesRead > maximumProcessCommandBytes || argumentCountExceeded,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
await handle.close();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const readLinuxIdentity = async (pidArg) => {
|
|
98
|
+
const [statBuffer, command] = await Promise.all([
|
|
99
|
+
plugins.fs.promises.readFile(`/proc/${pidArg}/stat`),
|
|
100
|
+
readBoundedLinuxCommandArguments(pidArg),
|
|
101
|
+
]);
|
|
102
|
+
const stat = statBuffer.toString('utf8');
|
|
103
|
+
const statSuffixIndex = stat.lastIndexOf(') ');
|
|
104
|
+
if (statSuffixIndex < 0)
|
|
105
|
+
throw new Error('Unable to parse controller process metadata.');
|
|
106
|
+
const statFields = stat.slice(statSuffixIndex + 2).trim().split(/\s+/);
|
|
107
|
+
const processGroupId = Number(statFields[2]);
|
|
108
|
+
const startTime = statFields[19];
|
|
109
|
+
if (!Number.isSafeInteger(processGroupId) || !startTime) {
|
|
110
|
+
throw new Error('Unable to parse controller process identity.');
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
pid: pidArg,
|
|
114
|
+
processGroupId,
|
|
115
|
+
processGroupLeader: processGroupId === pidArg,
|
|
116
|
+
arguments: command.arguments,
|
|
117
|
+
...(command.truncated ? { argumentsTruncated: true } : {}),
|
|
118
|
+
fingerprint: `linux:${pidArg}:${startTime}`,
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const readLinuxProcessGroupId = async (pidArg) => {
|
|
122
|
+
try {
|
|
123
|
+
const stat = await plugins.fs.promises.readFile(`/proc/${pidArg}/stat`, 'utf8');
|
|
124
|
+
const statSuffixIndex = stat.lastIndexOf(') ');
|
|
125
|
+
if (statSuffixIndex < 0)
|
|
126
|
+
return undefined;
|
|
127
|
+
const statFields = stat.slice(statSuffixIndex + 2).trim().split(/\s+/);
|
|
128
|
+
const processGroupId = Number(statFields[2]);
|
|
129
|
+
return Number.isSafeInteger(processGroupId) ? processGroupId : undefined;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
const code = error.code;
|
|
133
|
+
if (code === 'ENOENT' || code === 'ESRCH' || code === 'EACCES')
|
|
134
|
+
return undefined;
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const readPosixIdentity = async (pidArg) => {
|
|
139
|
+
const output = await execFile('ps', [
|
|
140
|
+
'-ww',
|
|
141
|
+
'-p',
|
|
142
|
+
String(pidArg),
|
|
143
|
+
'-o',
|
|
144
|
+
'pgid=',
|
|
145
|
+
'-o',
|
|
146
|
+
'lstart=',
|
|
147
|
+
'-o',
|
|
148
|
+
'command=',
|
|
149
|
+
], { maxBufferBytes: 8 * 1024 * 1024 });
|
|
150
|
+
const line = output.trim();
|
|
151
|
+
const match = /^\s*(\d+)\s+(.{24})\s+(.+)$/.exec(line);
|
|
152
|
+
if (!match)
|
|
153
|
+
throw new Error('Unable to parse controller process metadata.');
|
|
154
|
+
const processGroupId = Number(match[1]);
|
|
155
|
+
return {
|
|
156
|
+
pid: pidArg,
|
|
157
|
+
processGroupId,
|
|
158
|
+
processGroupLeader: processGroupId === pidArg,
|
|
159
|
+
arguments: parsePosixCommandArguments(match[3]),
|
|
160
|
+
fingerprint: `posix:${pidArg}:${match[2].trim()}`,
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
const parsePosixCommandArguments = (commandArg) => {
|
|
164
|
+
return (commandArg.match(/"[^"]*"|'[^']*'|\S+/g) ?? []).map((argumentArg) => {
|
|
165
|
+
const quoted = ((argumentArg.startsWith('"') && argumentArg.endsWith('"'))
|
|
166
|
+
|| (argumentArg.startsWith("'") && argumentArg.endsWith("'")));
|
|
167
|
+
return quoted ? argumentArg.slice(1, -1) : argumentArg;
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
export const readControllerProcessIdentity = async (pidArg) => {
|
|
171
|
+
const pid = assertPid(pidArg);
|
|
172
|
+
try {
|
|
173
|
+
if (process.platform === 'linux')
|
|
174
|
+
return await readLinuxIdentity(pid);
|
|
175
|
+
if (process.platform !== 'win32')
|
|
176
|
+
return await readPosixIdentity(pid);
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
const code = error.code;
|
|
181
|
+
if (code === 'ENOENT' || code === 'ESRCH')
|
|
182
|
+
return null;
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
export const readProcessGroupMemberPids = async (processGroupIdArg) => {
|
|
187
|
+
const processGroupId = assertPid(processGroupIdArg);
|
|
188
|
+
if (process.platform === 'linux') {
|
|
189
|
+
const entries = await plugins.fs.promises.readdir('/proc');
|
|
190
|
+
const processIds = entries
|
|
191
|
+
.filter((entryArg) => /^[1-9][0-9]*$/.test(entryArg))
|
|
192
|
+
.map((entryArg) => Number(entryArg))
|
|
193
|
+
.filter((processIdArg) => processIdArg >= 2);
|
|
194
|
+
const groupIds = await Promise.all(processIds.map(async (processIdArg) => ({
|
|
195
|
+
processId: processIdArg,
|
|
196
|
+
processGroupId: await readLinuxProcessGroupId(processIdArg),
|
|
197
|
+
})));
|
|
198
|
+
return groupIds
|
|
199
|
+
.filter((entryArg) => entryArg.processGroupId === processGroupId)
|
|
200
|
+
.map((entryArg) => entryArg.processId)
|
|
201
|
+
.sort((leftArg, rightArg) => leftArg - rightArg);
|
|
202
|
+
}
|
|
203
|
+
if (process.platform !== 'win32') {
|
|
204
|
+
// A detached helper gets its own process group, so macOS `ps -ax` cannot
|
|
205
|
+
// report the probe itself as a member of the controller group being read.
|
|
206
|
+
const output = await execFile('ps', ['-ax', '-o', 'pid=', '-o', 'pgid='], { detached: true });
|
|
207
|
+
return output
|
|
208
|
+
.split(/\r?\n/)
|
|
209
|
+
.map((lineArg) => /^\s*(\d+)\s+(\d+)\s*$/.exec(lineArg))
|
|
210
|
+
.filter((matchArg) => matchArg !== null)
|
|
211
|
+
.filter((matchArg) => Number(matchArg[2]) === processGroupId)
|
|
212
|
+
.map((matchArg) => Number(matchArg[1]))
|
|
213
|
+
.sort((leftArg, rightArg) => leftArg - rightArg);
|
|
214
|
+
}
|
|
215
|
+
return [];
|
|
216
|
+
};
|
|
217
|
+
const findCliArgumentIndex = async (pidArg, argumentsArg, cliPathArg, allowMissingAbsolutePathArg = false) => {
|
|
218
|
+
const boundedArguments = boundedProcessArgumentsPrefix(argumentsArg);
|
|
219
|
+
const directIndex = boundedArguments.indexOf(cliPathArg);
|
|
220
|
+
if (directIndex >= 0)
|
|
221
|
+
return directIndex;
|
|
222
|
+
// A controller launched with a relative path (`node cli.js foreground`) is
|
|
223
|
+
// still the same file; resolve candidate tokens against the process's own
|
|
224
|
+
// working directory before declaring the identity unverifiable.
|
|
225
|
+
let processCwd;
|
|
226
|
+
if (process.platform === 'linux') {
|
|
227
|
+
try {
|
|
228
|
+
processCwd = await plugins.fs.promises.readlink(`/proc/${pidArg}/cwd`);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
processCwd = undefined;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const cliBasename = plugins.path.basename(cliPathArg);
|
|
235
|
+
const normalizedCliPath = plugins.path.normalize(cliPathArg);
|
|
236
|
+
for (let endIndex = 1; endIndex <= boundedArguments.length; endIndex++) {
|
|
237
|
+
const minimumStartIndex = Math.max(0, endIndex - maximumReconstructedPathArguments);
|
|
238
|
+
for (let startIndex = endIndex - 1; startIndex >= minimumStartIndex; startIndex--) {
|
|
239
|
+
const candidate = boundedArguments.slice(startIndex, endIndex).join(' ');
|
|
240
|
+
if (plugins.path.basename(candidate) !== cliBasename)
|
|
241
|
+
continue;
|
|
242
|
+
try {
|
|
243
|
+
const resolved = await plugins.fs.promises.realpath(plugins.path.isAbsolute(candidate)
|
|
244
|
+
? candidate
|
|
245
|
+
: plugins.path.resolve(processCwd ?? '', candidate));
|
|
246
|
+
if (resolved === cliPathArg)
|
|
247
|
+
return endIndex - 1;
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
// pnpm may remove A's package while its worker still owns the upgrade
|
|
251
|
+
// lock. Only that trusted caller may use an exact normalized old path.
|
|
252
|
+
if (allowMissingAbsolutePathArg
|
|
253
|
+
&& plugins.path.isAbsolute(candidate)
|
|
254
|
+
&& plugins.path.normalize(candidate) === normalizedCliPath)
|
|
255
|
+
return endIndex - 1;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return -1;
|
|
261
|
+
};
|
|
262
|
+
export const processIdentityHasFileArgument = async (identityArg, filePathArg, optionsArg = {}) => await findCliArgumentIndex(identityArg.pid, identityArg.arguments, filePathArg, optionsArg.allowMissingAbsolutePath === true) >= 0;
|
|
263
|
+
const findInstalledControllerPackageFileArgumentIndex = (argumentsArg, packageRelativePathArg) => {
|
|
264
|
+
const boundedArguments = boundedProcessArgumentsPrefix(argumentsArg);
|
|
265
|
+
const expectedSuffixes = installedControllerPackagePaths.map((packagePathArg) => (`${plugins.path.sep}${plugins.path.join(packagePathArg, packageRelativePathArg)}`));
|
|
266
|
+
const expectedBasename = plugins.path.basename(packageRelativePathArg);
|
|
267
|
+
for (let endIndex = 1; endIndex <= boundedArguments.length; endIndex++) {
|
|
268
|
+
const minimumStartIndex = Math.max(0, endIndex - maximumReconstructedPathArguments);
|
|
269
|
+
for (let startIndex = endIndex - 1; startIndex >= minimumStartIndex; startIndex--) {
|
|
270
|
+
const candidate = boundedArguments.slice(startIndex, endIndex).join(' ');
|
|
271
|
+
if (plugins.path.basename(candidate) === expectedBasename
|
|
272
|
+
&& plugins.path.isAbsolute(candidate)
|
|
273
|
+
&& expectedSuffixes.some((suffixArg) => (plugins.path.normalize(candidate).endsWith(suffixArg))))
|
|
274
|
+
return endIndex - 1;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return -1;
|
|
278
|
+
};
|
|
279
|
+
const processIdentityHasInstalledControllerCommand = (identityArg, commandArg) => {
|
|
280
|
+
const cliIndex = findInstalledControllerPackageFileArgumentIndex(identityArg.arguments, 'cli.js');
|
|
281
|
+
return cliIndex >= 0 && identityArg.arguments[cliIndex + 1] === commandArg;
|
|
282
|
+
};
|
|
283
|
+
const readEffectiveArgvPort = (argumentsArg) => {
|
|
284
|
+
let effectivePort = defaultControllerPort;
|
|
285
|
+
const boundedArguments = boundedProcessArgumentsPrefix(argumentsArg);
|
|
286
|
+
for (let index = 0; index < boundedArguments.length; index++) {
|
|
287
|
+
if (boundedArguments[index] === '--port') {
|
|
288
|
+
effectivePort = Number(boundedArguments[index + 1]);
|
|
289
|
+
}
|
|
290
|
+
else if (boundedArguments[index].startsWith('--port=')) {
|
|
291
|
+
effectivePort = Number(boundedArguments[index].slice('--port='.length));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return effectivePort;
|
|
295
|
+
};
|
|
296
|
+
export const processIdentityHasCliCommand = async (identityArg, cliPathArg, commandArg, optionsArg = {}) => {
|
|
297
|
+
const cliIndex = await findCliArgumentIndex(identityArg.pid, identityArg.arguments, cliPathArg, optionsArg.allowMissingAbsolutePath === true);
|
|
298
|
+
return cliIndex >= 0 && identityArg.arguments[cliIndex + 1] === commandArg;
|
|
299
|
+
};
|
|
300
|
+
const hasExpectedArguments = async (identityArg, cliPathArg, portArg, commandArg) => {
|
|
301
|
+
return await processIdentityHasCliCommand(identityArg, cliPathArg, commandArg)
|
|
302
|
+
&& readEffectiveArgvPort(identityArg.arguments) === portArg;
|
|
303
|
+
};
|
|
304
|
+
const visitProcessIdentities = async (visitorArg) => {
|
|
305
|
+
if (process.platform === 'linux') {
|
|
306
|
+
const entries = await plugins.fs.promises.readdir('/proc');
|
|
307
|
+
const processIds = entries
|
|
308
|
+
.filter((entryArg) => /^[1-9][0-9]*$/.test(entryArg))
|
|
309
|
+
.map((entryArg) => Number(entryArg))
|
|
310
|
+
.filter((processIdArg) => processIdArg >= 2)
|
|
311
|
+
.sort((leftArg, rightArg) => leftArg - rightArg);
|
|
312
|
+
if (processIds.length > maximumProcessIdentities) {
|
|
313
|
+
throw new Error('Controller data-writer process inventory exceeds its scan bound.');
|
|
314
|
+
}
|
|
315
|
+
for (let index = 0; index < processIds.length; index += processIdentityBatchSize) {
|
|
316
|
+
const batch = await Promise.all(processIds.slice(index, index + processIdentityBatchSize).map(async (processIdArg) => {
|
|
317
|
+
try {
|
|
318
|
+
return await readControllerProcessIdentity(processIdArg);
|
|
319
|
+
}
|
|
320
|
+
catch (errorArg) {
|
|
321
|
+
const code = errorArg.code;
|
|
322
|
+
if (code === 'EACCES' || code === 'EPERM')
|
|
323
|
+
return null;
|
|
324
|
+
throw errorArg;
|
|
325
|
+
}
|
|
326
|
+
}));
|
|
327
|
+
for (const identity of batch) {
|
|
328
|
+
if (identity)
|
|
329
|
+
await visitorArg(identity);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
if (process.platform === 'win32')
|
|
335
|
+
return;
|
|
336
|
+
const output = await execFile('ps', [
|
|
337
|
+
'-ax',
|
|
338
|
+
'-ww',
|
|
339
|
+
'-o',
|
|
340
|
+
'pid=',
|
|
341
|
+
'-o',
|
|
342
|
+
'pgid=',
|
|
343
|
+
'-o',
|
|
344
|
+
'lstart=',
|
|
345
|
+
'-o',
|
|
346
|
+
'command=',
|
|
347
|
+
], { maxBufferBytes: 8 * 1024 * 1024 });
|
|
348
|
+
let identityCount = 0;
|
|
349
|
+
for (const lineArg of output.split(/\r?\n/)) {
|
|
350
|
+
const match = /^\s*(\d+)\s+(\d+)\s+(.{24})\s+(.+)$/.exec(lineArg);
|
|
351
|
+
if (!match)
|
|
352
|
+
continue;
|
|
353
|
+
const pid = Number(match[1]);
|
|
354
|
+
const processGroupId = Number(match[2]);
|
|
355
|
+
if (!Number.isSafeInteger(pid) || !Number.isSafeInteger(processGroupId))
|
|
356
|
+
continue;
|
|
357
|
+
identityCount += 1;
|
|
358
|
+
if (identityCount > maximumProcessIdentities) {
|
|
359
|
+
throw new Error('Controller data-writer process inventory exceeds its scan bound.');
|
|
360
|
+
}
|
|
361
|
+
await visitorArg({
|
|
362
|
+
pid,
|
|
363
|
+
processGroupId,
|
|
364
|
+
processGroupLeader: processGroupId === pid,
|
|
365
|
+
arguments: parsePosixCommandArguments(match[4]),
|
|
366
|
+
fingerprint: `posix:${pid}:${match[3].trim()}`,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
const compactProcessIdentity = (identityArg) => ({
|
|
371
|
+
...identityArg,
|
|
372
|
+
arguments: [],
|
|
373
|
+
});
|
|
374
|
+
export const listControllerProcessesForCli = async (cliPathArg) => {
|
|
375
|
+
const candidates = [];
|
|
376
|
+
await visitProcessIdentities(async (identity) => {
|
|
377
|
+
for (const command of ['__serve', 'foreground']) {
|
|
378
|
+
if (!await processIdentityHasCliCommand(identity, cliPathArg, command))
|
|
379
|
+
continue;
|
|
380
|
+
const port = readEffectiveArgvPort(identity.arguments);
|
|
381
|
+
if (!Number.isSafeInteger(port) || port < 1 || port > 65_535) {
|
|
382
|
+
throw new Error(`An ${currentRuntimeName} process has an invalid port argument (PID ${identity.pid}).`);
|
|
383
|
+
}
|
|
384
|
+
candidates.push({ identity: compactProcessIdentity(identity), command, port });
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
return candidates.sort((leftArg, rightArg) => leftArg.identity.pid - rightArg.identity.pid);
|
|
388
|
+
};
|
|
389
|
+
export const listControllerDataWriterProcessesForCli = async (cliPathArg, optionsArg = {}) => await listControllerDataWriterProcessesForCliPaths([cliPathArg], optionsArg);
|
|
390
|
+
export const listControllerDataWriterProcessesForCliPaths = async (cliPathsArg, optionsArg = {}) => {
|
|
391
|
+
const cliPaths = [...new Set(cliPathsArg)];
|
|
392
|
+
if (cliPaths.length === 0
|
|
393
|
+
|| cliPaths.length > maximumDataWriterCliPaths
|
|
394
|
+
|| cliPaths.some((cliPathArg) => !plugins.path.isAbsolute(cliPathArg)))
|
|
395
|
+
throw new Error('Controller data-writer CLI path inventory is invalid.');
|
|
396
|
+
const flexChildPaths = cliPaths.map((cliPathArg) => plugins.path.join(plugins.path.dirname(cliPathArg), 'dist_ts', 'flexharness.child.js'));
|
|
397
|
+
const candidates = [];
|
|
398
|
+
await visitProcessIdentities(async (identity) => {
|
|
399
|
+
let matched = false;
|
|
400
|
+
for (const cliPath of cliPaths) {
|
|
401
|
+
if (await processIdentityHasCliCommand(identity, cliPath, '__serve')
|
|
402
|
+
|| await processIdentityHasCliCommand(identity, cliPath, 'foreground')) {
|
|
403
|
+
matched = true;
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (!matched
|
|
408
|
+
&& optionsArg.includeInstalledPackagePaths === true
|
|
409
|
+
&& (processIdentityHasInstalledControllerCommand(identity, '__serve')
|
|
410
|
+
|| processIdentityHasInstalledControllerCommand(identity, 'foreground')))
|
|
411
|
+
matched = true;
|
|
412
|
+
if (matched) {
|
|
413
|
+
if (candidates.length >= maximumDataWriterCandidates) {
|
|
414
|
+
throw new Error('Controller data-writer candidate inventory exceeds its scan bound.');
|
|
415
|
+
}
|
|
416
|
+
candidates.push({ kind: 'controller', identity: compactProcessIdentity(identity) });
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
for (const cliPath of cliPaths) {
|
|
420
|
+
if (await processIdentityHasCliCommand(identity, cliPath, 'temp-password')) {
|
|
421
|
+
matched = true;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (!matched
|
|
426
|
+
&& optionsArg.includeInstalledPackagePaths === true
|
|
427
|
+
&& processIdentityHasInstalledControllerCommand(identity, 'temp-password'))
|
|
428
|
+
matched = true;
|
|
429
|
+
if (matched) {
|
|
430
|
+
if (candidates.length >= maximumDataWriterCandidates) {
|
|
431
|
+
throw new Error('Controller data-writer candidate inventory exceeds its scan bound.');
|
|
432
|
+
}
|
|
433
|
+
candidates.push({ kind: 'temp-password', identity: compactProcessIdentity(identity) });
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
for (const flexChildPath of flexChildPaths) {
|
|
437
|
+
if (await processIdentityHasFileArgument(identity, flexChildPath)) {
|
|
438
|
+
matched = true;
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (!matched
|
|
443
|
+
&& optionsArg.includeInstalledPackagePaths === true
|
|
444
|
+
&& findInstalledControllerPackageFileArgumentIndex(identity.arguments, plugins.path.join('dist_ts', 'flexharness.child.js')) >= 0)
|
|
445
|
+
matched = true;
|
|
446
|
+
if (matched) {
|
|
447
|
+
if (candidates.length >= maximumDataWriterCandidates) {
|
|
448
|
+
throw new Error('Controller data-writer candidate inventory exceeds its scan bound.');
|
|
449
|
+
}
|
|
450
|
+
candidates.push({ kind: 'flex-child', identity: compactProcessIdentity(identity) });
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
return candidates.sort((leftArg, rightArg) => leftArg.identity.pid - rightArg.identity.pid);
|
|
454
|
+
};
|
|
455
|
+
export const inspectControllerProcess = async (optionsArg) => {
|
|
456
|
+
const identity = await readControllerProcessIdentity(optionsArg.pid);
|
|
457
|
+
if (!identity)
|
|
458
|
+
return null;
|
|
459
|
+
if (!await hasExpectedArguments(identity, optionsArg.cliPath, optionsArg.port, optionsArg.command)) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
if (optionsArg.expectedProcessGroupId !== undefined
|
|
463
|
+
&& identity.processGroupId !== optionsArg.expectedProcessGroupId)
|
|
464
|
+
return null;
|
|
465
|
+
if (optionsArg.expectedFingerprint !== undefined
|
|
466
|
+
&& identity.fingerprint !== optionsArg.expectedFingerprint)
|
|
467
|
+
return null;
|
|
468
|
+
return identity;
|
|
469
|
+
};
|
|
470
|
+
export const signalVerifiedControllerProcess = async (optionsArg) => {
|
|
471
|
+
const identity = await inspectControllerProcess(optionsArg);
|
|
472
|
+
if (!identity) {
|
|
473
|
+
throw new Error('Refusing to signal a process whose controller identity cannot be verified.');
|
|
474
|
+
}
|
|
475
|
+
if (optionsArg.signalProcessGroup) {
|
|
476
|
+
if (!identity.processGroupLeader) {
|
|
477
|
+
throw new Error('Refusing to signal a process group whose controller is not its leader.');
|
|
478
|
+
}
|
|
479
|
+
process.kill(-identity.processGroupId, optionsArg.signal);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
process.kill(identity.pid, optionsArg.signal);
|
|
483
|
+
};
|
|
484
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wcm9jZXNzaW5zcGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NsYXNzZXMucHJvY2Vzc2luc3BlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbEUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFzQjVELE1BQU0sd0JBQXdCLEdBQUcsTUFBTSxDQUFDO0FBQ3hDLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBQ3JDLE1BQU0sdUJBQXVCLEdBQUcsR0FBRyxDQUFDO0FBQ3BDLE1BQU0sMkJBQTJCLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQztBQUMvQyxNQUFNLDBCQUEwQixHQUFHLDJCQUEyQixHQUFHLHVCQUF1QixDQUFDO0FBQ3pGLE1BQU0saUNBQWlDLEdBQUcsRUFBRSxDQUFDO0FBQzdDLE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxDQUFDO0FBQ3BDLE1BQU0sMkJBQTJCLEdBQUcsS0FBSyxDQUFDO0FBQzFDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDLHFCQUFxQixDQUFDLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztBQUNwRixNQUFNLCtCQUErQixHQUFHO0lBQ3RDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsRUFBRSxtQkFBbUIsRUFBRSxvQkFBb0IsQ0FBQztJQUM1RSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDO0NBQ2hDLENBQUM7QUFFWCxNQUFNLDZCQUE2QixHQUFHLENBQUMsWUFBK0IsRUFBWSxFQUFFO0lBQ2xGLE1BQU0sT0FBTyxHQUFhLEVBQUUsQ0FBQztJQUM3QixJQUFJ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
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type TControllerResource, type TControllerSessionId } from '../dist_ts_interfaces/index.js';
|
|
2
|
+
import type { SmartDataAuthStore } from './classes.authstore.js';
|
|
3
|
+
import type { IControllerResourceDocument } from './interfaces.projects.js';
|
|
4
|
+
import { type IFlexBrowserResourceDescriptor } from './interfaces.flexipc.js';
|
|
5
|
+
export interface IControllerResourceRuntimeHost {
|
|
6
|
+
startResource(resourceArg: IControllerResourceDocument, signalArg: AbortSignal): Promise<void>;
|
|
7
|
+
stopResource(resourceArg: IControllerResourceDocument, signalArg: AbortSignal): Promise<void>;
|
|
8
|
+
isRunning(resourceArg: IControllerResourceDocument): boolean;
|
|
9
|
+
isAvailable(): boolean;
|
|
10
|
+
renameResource?(resourceArg: IControllerResourceDocument): Promise<void>;
|
|
11
|
+
reconcileAttachment(resourceArg: IControllerResourceDocument, signalArg: AbortSignal): Promise<void>;
|
|
12
|
+
retireResource(resourceArg: IControllerResourceDocument, signalArg: AbortSignal): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export interface IControllerResourceCoordinatorOptions {
|
|
15
|
+
store: Pick<SmartDataAuthStore, 'listResources' | 'listRecoverableResources' | 'createResource' | 'renameResource' | 'beginResourceAttachmentTransition' | 'commitResourceAttachmentTransition' | 'beginResourceRetirement' | 'completeResourceRetirement'>;
|
|
16
|
+
terminalHost: IControllerResourceRuntimeHost;
|
|
17
|
+
browserHost: IControllerResourceRuntimeHost;
|
|
18
|
+
isFlexHarnessAvailable(): boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class ControllerResourceUnavailableError extends Error {
|
|
21
|
+
readonly code = "resource_unavailable";
|
|
22
|
+
constructor(messageArg: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class ControllerProjectHasResourcesError extends Error {
|
|
25
|
+
readonly resourceIds: string[];
|
|
26
|
+
readonly code = "project_has_resources";
|
|
27
|
+
constructor(resourceIds: string[]);
|
|
28
|
+
}
|
|
29
|
+
export declare class ControllerResourceCoordinator {
|
|
30
|
+
private readonly options;
|
|
31
|
+
private readonly projectStates;
|
|
32
|
+
private readonly deletingSessions;
|
|
33
|
+
constructor(options: IControllerResourceCoordinatorOptions);
|
|
34
|
+
listResources(projectIdArg: string): Promise<TControllerResource[]>;
|
|
35
|
+
requireResourceKind(projectIdArg: string, resourceIdArg: string, kindArg: IControllerResourceDocument['kind']): Promise<boolean>;
|
|
36
|
+
createResource(inputArg: Parameters<SmartDataAuthStore['createResource']>[0], signalArg: AbortSignal): Promise<TControllerResource>;
|
|
37
|
+
renameResource(projectIdArg: string, resourceIdArg: string, titleArg: string): Promise<TControllerResource>;
|
|
38
|
+
changeAttachment(inputArg: {
|
|
39
|
+
projectId: string;
|
|
40
|
+
resourceId: string;
|
|
41
|
+
sessionId: TControllerSessionId | null;
|
|
42
|
+
expectedAttachmentRevision: number;
|
|
43
|
+
signal: AbortSignal;
|
|
44
|
+
}): Promise<TControllerResource>;
|
|
45
|
+
retireResource(projectIdArg: string, resourceIdArg: string, signalArg: AbortSignal): Promise<void>;
|
|
46
|
+
startResource(projectIdArg: string, resourceIdArg: string, signalArg: AbortSignal): Promise<TControllerResource>;
|
|
47
|
+
stopResource(projectIdArg: string, resourceIdArg: string, signalArg: AbortSignal): Promise<TControllerResource>;
|
|
48
|
+
recover(signalArg: AbortSignal): Promise<void>;
|
|
49
|
+
withSessionDeletion<T>(projectIdArg: string, sessionIdArg: TControllerSessionId, signalArg: AbortSignal, deleteArg: () => Promise<T>): Promise<T>;
|
|
50
|
+
withProjectRemovalGuard<T>(projectIdArg: string, removeArg: () => Promise<T>): Promise<T>;
|
|
51
|
+
resolveFlexBrowserResources(projectIdArg: string, sessionIdArg: string): Promise<IFlexBrowserResourceDescriptor[]>;
|
|
52
|
+
requireFlexBrowserResource(inputArg: {
|
|
53
|
+
projectId: string;
|
|
54
|
+
sessionId: string;
|
|
55
|
+
resourceId: string;
|
|
56
|
+
attachmentRevision: number;
|
|
57
|
+
}): Promise<IControllerResourceDocument>;
|
|
58
|
+
private reconcilePendingAttachment;
|
|
59
|
+
private toPublicResource;
|
|
60
|
+
private hostFor;
|
|
61
|
+
private projectState;
|
|
62
|
+
private runProjectMutation;
|
|
63
|
+
private sessionKey;
|
|
64
|
+
}
|