cyclops-clientdevbridge-cli 0.1.1
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/CHANGELOG.md +41 -0
- package/LICENSE +21 -0
- package/README.md +218 -0
- package/dist/artifacts.d.ts +56 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +58 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +348 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/compare.d.ts +27 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +209 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/context.d.ts +25 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +36 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/doctor.d.ts +31 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +234 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/hotswap.d.ts +7 -0
- package/dist/commands/hotswap.d.ts.map +1 -0
- package/dist/commands/hotswap.js +76 -0
- package/dist/commands/hotswap.js.map +1 -0
- package/dist/commands/input.d.ts +53 -0
- package/dist/commands/input.d.ts.map +1 -0
- package/dist/commands/input.js +204 -0
- package/dist/commands/input.js.map +1 -0
- package/dist/commands/inspect.d.ts +19 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +90 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/lifecycle.d.ts +29 -0
- package/dist/commands/lifecycle.d.ts.map +1 -0
- package/dist/commands/lifecycle.js +201 -0
- package/dist/commands/lifecycle.js.map +1 -0
- package/dist/commands/snapshot.d.ts +37 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +133 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/world.d.ts +27 -0
- package/dist/commands/world.d.ts.map +1 -0
- package/dist/commands/world.js +203 -0
- package/dist/commands/world.js.map +1 -0
- package/dist/detect.d.ts +58 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +185 -0
- package/dist/detect.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +37 -0
- package/dist/errors.js.map +1 -0
- package/dist/hotswap.d.ts +58 -0
- package/dist/hotswap.d.ts.map +1 -0
- package/dist/hotswap.js +284 -0
- package/dist/hotswap.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/initscript.d.ts +49 -0
- package/dist/initscript.d.ts.map +1 -0
- package/dist/initscript.js +202 -0
- package/dist/initscript.js.map +1 -0
- package/dist/java.d.ts +47 -0
- package/dist/java.d.ts.map +1 -0
- package/dist/java.js +114 -0
- package/dist/java.js.map +1 -0
- package/dist/launcher.d.ts +104 -0
- package/dist/launcher.d.ts.map +1 -0
- package/dist/launcher.js +609 -0
- package/dist/launcher.js.map +1 -0
- package/dist/loopback.d.ts +17 -0
- package/dist/loopback.d.ts.map +1 -0
- package/dist/loopback.js +19 -0
- package/dist/loopback.js.map +1 -0
- package/dist/output.d.ts +21 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +41 -0
- package/dist/output.js.map +1 -0
- package/dist/paths.d.ts +23 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +47 -0
- package/dist/paths.js.map +1 -0
- package/dist/protocol/client.d.ts +35 -0
- package/dist/protocol/client.d.ts.map +1 -0
- package/dist/protocol/client.js +170 -0
- package/dist/protocol/client.js.map +1 -0
- package/dist/protocol/types.d.ts +114 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +38 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/session.d.ts +77 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +79 -0
- package/dist/session.js.map +1 -0
- package/dist/snapshot/model.d.ts +327 -0
- package/dist/snapshot/model.d.ts.map +1 -0
- package/dist/snapshot/model.js +91 -0
- package/dist/snapshot/model.js.map +1 -0
- package/dist/snapshot/outline.d.ts +35 -0
- package/dist/snapshot/outline.d.ts.map +1 -0
- package/dist/snapshot/outline.js +135 -0
- package/dist/snapshot/outline.js.map +1 -0
- package/dist/xvfb.d.ts +30 -0
- package/dist/xvfb.d.ts.map +1 -0
- package/dist/xvfb.js +66 -0
- package/dist/xvfb.js.map +1 -0
- package/package.json +66 -0
package/dist/loopback.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The loopback addresses a ClientDevBridge client may be listening on.
|
|
3
|
+
*
|
|
4
|
+
* 127.0.0.1 is what the mod binds, and the only address it has ever meant to bind. But a client
|
|
5
|
+
* built before that was made explicit calls `InetAddress.getLoopbackAddress()`, and NeoForge's dev
|
|
6
|
+
* run configuration passes `-Djava.net.preferIPv6Addresses=system`, under which the JDK answers
|
|
7
|
+
* `::1` on any machine that has `::1` bound. Such a client is perfectly healthy and completely
|
|
8
|
+
* unreachable on 127.0.0.1, so the CLI tries both rather than making the two versions move
|
|
9
|
+
* together.
|
|
10
|
+
*
|
|
11
|
+
* IPv4 comes first: it is the normal case, and trying it first keeps the usual error message the
|
|
12
|
+
* IPv4 one.
|
|
13
|
+
*/
|
|
14
|
+
export const LOOPBACK_HOSTS = ['127.0.0.1', '::1'];
|
|
15
|
+
/** Wraps an IPv6 literal in the brackets a URL authority needs; IPv4 passes through. */
|
|
16
|
+
export function urlHost(host) {
|
|
17
|
+
return host.includes(':') ? `[${host}]` : host;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=loopback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback.js","sourceRoot":"","sources":["../src/loopback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,KAAK,CAAU,CAAC;AAE5D,wFAAwF;AACxF,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output conventions (plan §5), in one place so every command obeys them.
|
|
3
|
+
*
|
|
4
|
+
* - Default output is text meant to be read by a human or an agent; `--json` prints the raw
|
|
5
|
+
* protocol result instead.
|
|
6
|
+
* - Images are never printed. A screenshot writes a file and prints its absolute path on its
|
|
7
|
+
* own line, so an agent can hand that path straight to a file-reading tool.
|
|
8
|
+
*/
|
|
9
|
+
export interface OutputOptions {
|
|
10
|
+
readonly json: boolean;
|
|
11
|
+
readonly quiet: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function printJson(value: unknown): void;
|
|
14
|
+
export declare function line(text?: string): void;
|
|
15
|
+
/** Prints a path on its own line, which is the contract for every file the CLI produces. */
|
|
16
|
+
export declare function printPath(absolutePath: string): void;
|
|
17
|
+
export declare function warn(text: string): void;
|
|
18
|
+
export declare function keyValues(entries: readonly (readonly [string, unknown])[]): void;
|
|
19
|
+
/** Renders a duration the way a person reads it, for `status`. */
|
|
20
|
+
export declare function formatDuration(ms: number): string;
|
|
21
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE9C;AAED,wBAAgB,IAAI,CAAC,IAAI,SAAK,GAAG,IAAI,CAEpC;AAED,4FAA4F;AAC5F,wBAAgB,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEvC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,GAAG,IAAI,CAKhF;AAYD,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAUjD"}
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function printJson(value) {
|
|
2
|
+
process.stdout.write(`${JSON.stringify(value, null, 2)}\n`);
|
|
3
|
+
}
|
|
4
|
+
export function line(text = '') {
|
|
5
|
+
process.stdout.write(`${text}\n`);
|
|
6
|
+
}
|
|
7
|
+
/** Prints a path on its own line, which is the contract for every file the CLI produces. */
|
|
8
|
+
export function printPath(absolutePath) {
|
|
9
|
+
process.stdout.write(`${absolutePath}\n`);
|
|
10
|
+
}
|
|
11
|
+
export function warn(text) {
|
|
12
|
+
process.stderr.write(`warning: ${text}\n`);
|
|
13
|
+
}
|
|
14
|
+
export function keyValues(entries) {
|
|
15
|
+
const width = Math.max(...entries.map(([key]) => key.length));
|
|
16
|
+
for (const [key, value] of entries) {
|
|
17
|
+
line(`${key.padEnd(width)} ${formatValue(value)}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function formatValue(value) {
|
|
21
|
+
if (value === null || value === undefined) {
|
|
22
|
+
return '-';
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
return value.length === 0 ? '-' : value.join(', ');
|
|
26
|
+
}
|
|
27
|
+
return String(value);
|
|
28
|
+
}
|
|
29
|
+
/** Renders a duration the way a person reads it, for `status`. */
|
|
30
|
+
export function formatDuration(ms) {
|
|
31
|
+
const seconds = Math.floor(ms / 1000);
|
|
32
|
+
if (seconds < 60) {
|
|
33
|
+
return `${seconds}s`;
|
|
34
|
+
}
|
|
35
|
+
const minutes = Math.floor(seconds / 60);
|
|
36
|
+
if (minutes < 60) {
|
|
37
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
38
|
+
}
|
|
39
|
+
return `${Math.floor(minutes / 60)}h ${minutes % 60}m`;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAI,GAAG,EAAE;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,SAAS,CAAC,YAAoB;IAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAgD;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACjB,OAAO,GAAG,OAAO,GAAG,CAAC;IACvB,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACzC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;QACjB,OAAO,GAAG,OAAO,KAAK,OAAO,GAAG,EAAE,GAAG,CAAC;IACxC,CAAC;IACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,KAAK,OAAO,GAAG,EAAE,GAAG,CAAC;AACzD,CAAC"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything a session writes lives under `<projectDir>/.clientdevbridge/`, so that a
|
|
3
|
+
* session is discoverable from a cold shell and disappears with the checkout.
|
|
4
|
+
*/
|
|
5
|
+
export interface BridgePaths {
|
|
6
|
+
readonly projectDir: string;
|
|
7
|
+
readonly root: string;
|
|
8
|
+
readonly sessionFile: string;
|
|
9
|
+
readonly gradleLog: string;
|
|
10
|
+
readonly screenshots: string;
|
|
11
|
+
readonly golden: string;
|
|
12
|
+
readonly diffs: string;
|
|
13
|
+
readonly initScript: string;
|
|
14
|
+
readonly hotswapState: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function resolvePaths(projectDir: string): BridgePaths;
|
|
17
|
+
export declare function ensureDirectories(paths: BridgePaths): void;
|
|
18
|
+
/**
|
|
19
|
+
* The generated session state is disposable, but golden images are committed alongside the
|
|
20
|
+
* consumer's code, so only the rest is ignored. Idempotent: re-running never duplicates the block.
|
|
21
|
+
*/
|
|
22
|
+
export declare function ensureGitignore(paths: BridgePaths): boolean;
|
|
23
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CAc5D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAI1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAoB3D"}
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
export function resolvePaths(projectDir) {
|
|
4
|
+
const resolved = path.resolve(projectDir);
|
|
5
|
+
const root = path.join(resolved, '.clientdevbridge');
|
|
6
|
+
return {
|
|
7
|
+
projectDir: resolved,
|
|
8
|
+
root,
|
|
9
|
+
sessionFile: path.join(root, 'session.json'),
|
|
10
|
+
gradleLog: path.join(root, 'gradle.log'),
|
|
11
|
+
screenshots: path.join(root, 'screenshots'),
|
|
12
|
+
golden: path.join(root, 'golden'),
|
|
13
|
+
diffs: path.join(root, 'diffs'),
|
|
14
|
+
initScript: path.join(root, 'init.gradle'),
|
|
15
|
+
hotswapState: path.join(root, 'hotswap'),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function ensureDirectories(paths) {
|
|
19
|
+
for (const dir of [paths.root, paths.screenshots, paths.golden, paths.diffs, paths.hotswapState]) {
|
|
20
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The generated session state is disposable, but golden images are committed alongside the
|
|
25
|
+
* consumer's code, so only the rest is ignored. Idempotent: re-running never duplicates the block.
|
|
26
|
+
*/
|
|
27
|
+
export function ensureGitignore(paths) {
|
|
28
|
+
const gitignorePath = path.join(paths.projectDir, '.gitignore');
|
|
29
|
+
const marker = '# ClientDevBridge session state (golden images are intentionally kept)';
|
|
30
|
+
const block = [
|
|
31
|
+
marker,
|
|
32
|
+
'.clientdevbridge/*',
|
|
33
|
+
'!.clientdevbridge/golden/',
|
|
34
|
+
'',
|
|
35
|
+
].join('\n');
|
|
36
|
+
let existing = '';
|
|
37
|
+
if (fs.existsSync(gitignorePath)) {
|
|
38
|
+
existing = fs.readFileSync(gitignorePath, 'utf8');
|
|
39
|
+
if (existing.includes(marker)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const separator = existing.length > 0 && !existing.endsWith('\n') ? '\n' : '';
|
|
44
|
+
fs.writeFileSync(gitignorePath, `${existing}${separator}${existing.length > 0 ? '\n' : ''}${block}`, 'utf8');
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAkBlC,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;IACrD,OAAO;QACL,UAAU,EAAE,QAAQ;QACpB,IAAI;QACJ,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC;QAC5C,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;QACxC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;QAC3C,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;QACjC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;QAC/B,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;QAC1C,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;KACzC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAkB;IAClD,KAAK,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QACjG,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAkB;IAChD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,wEAAwE,CAAC;IACxF,MAAM,KAAK,GAAG;QACZ,MAAM;QACN,oBAAoB;QACpB,2BAA2B;QAC3B,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACjC,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAClD,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,EAAE,CAAC,aAAa,CAAC,aAAa,EAAE,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;IAC7G,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Hello } from './types.js';
|
|
2
|
+
export type NotificationListener = (method: string, params: Record<string, unknown>) => void;
|
|
3
|
+
export interface ConnectOptions {
|
|
4
|
+
readonly port: number;
|
|
5
|
+
readonly timeoutMs?: number;
|
|
6
|
+
readonly onNotification?: NotificationListener;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A JSON-RPC 2.0 client over the mod's localhost WebSocket.
|
|
10
|
+
*
|
|
11
|
+
* One instance per CLI invocation: connect, do one thing, close.
|
|
12
|
+
*/
|
|
13
|
+
export declare class BridgeClient {
|
|
14
|
+
private readonly socket;
|
|
15
|
+
private readonly pending;
|
|
16
|
+
private readonly listeners;
|
|
17
|
+
private nextId;
|
|
18
|
+
private closedReason;
|
|
19
|
+
readonly hello: Hello;
|
|
20
|
+
private constructor();
|
|
21
|
+
/**
|
|
22
|
+
* Connects to the client on this port, over whichever loopback address it is listening on.
|
|
23
|
+
*
|
|
24
|
+
* The first address that answers wins. When none does, the failure reported is the one from
|
|
25
|
+
* 127.0.0.1: that is where a client is supposed to be, so it is the message that helps.
|
|
26
|
+
*/
|
|
27
|
+
static connect(options: ConnectOptions): Promise<BridgeClient>;
|
|
28
|
+
private static connectTo;
|
|
29
|
+
onNotification(listener: NotificationListener): void;
|
|
30
|
+
call<T = unknown>(method: string, params?: Record<string, unknown>, timeoutMs?: number): Promise<T>;
|
|
31
|
+
private onMessage;
|
|
32
|
+
private failAll;
|
|
33
|
+
close(): void;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/protocol/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,KAAK,EAA6E,MAAM,YAAY,CAAC;AAEnH,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAE7F,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,oBAAoB,CAAC;CAChD;AAOD;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8B;IACxD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,YAAY,CAAuB;IAE3C,SAAgB,KAAK,EAAE,KAAK,CAAC;IAE7B,OAAO;IAQP;;;;;OAKG;WACiB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;mBAYtD,SAAS;IAyEvB,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI;IAI9C,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,SAAS,SAAU,GAAG,OAAO,CAAC,CAAC,CAAC;IA2BrH,OAAO,CAAC,SAAS;IAiCjB,OAAO,CAAC,OAAO;IAQR,KAAK,IAAI,IAAI;CAIrB"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import { ProtocolError, SessionError } from '../errors.js';
|
|
3
|
+
import { LOOPBACK_HOSTS, urlHost } from '../loopback.js';
|
|
4
|
+
import { helloSchema, rpcNotificationSchema, rpcResponseSchema, SUPPORTED_PROTOCOL } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* A JSON-RPC 2.0 client over the mod's localhost WebSocket.
|
|
7
|
+
*
|
|
8
|
+
* One instance per CLI invocation: connect, do one thing, close.
|
|
9
|
+
*/
|
|
10
|
+
export class BridgeClient {
|
|
11
|
+
socket;
|
|
12
|
+
pending = new Map();
|
|
13
|
+
listeners = [];
|
|
14
|
+
nextId = 1;
|
|
15
|
+
closedReason = null;
|
|
16
|
+
hello;
|
|
17
|
+
constructor(socket, hello) {
|
|
18
|
+
this.socket = socket;
|
|
19
|
+
this.hello = hello;
|
|
20
|
+
socket.on('message', (raw) => this.onMessage(String(raw)));
|
|
21
|
+
socket.on('close', () => this.failAll('The client closed the connection.'));
|
|
22
|
+
socket.on('error', (error) => this.failAll(`Connection error: ${error.message}`));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Connects to the client on this port, over whichever loopback address it is listening on.
|
|
26
|
+
*
|
|
27
|
+
* The first address that answers wins. When none does, the failure reported is the one from
|
|
28
|
+
* 127.0.0.1: that is where a client is supposed to be, so it is the message that helps.
|
|
29
|
+
*/
|
|
30
|
+
static async connect(options) {
|
|
31
|
+
let first;
|
|
32
|
+
for (const host of LOOPBACK_HOSTS) {
|
|
33
|
+
try {
|
|
34
|
+
return await BridgeClient.connectTo(host, options);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
first ??= error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw first;
|
|
41
|
+
}
|
|
42
|
+
static async connectTo(host, options) {
|
|
43
|
+
const timeoutMs = options.timeoutMs ?? 15_000;
|
|
44
|
+
const url = `ws://${urlHost(host)}:${options.port}`;
|
|
45
|
+
const socket = new WebSocket(url, { handshakeTimeout: timeoutMs });
|
|
46
|
+
const early = [];
|
|
47
|
+
const hello = await new Promise((resolve, reject) => {
|
|
48
|
+
const timer = setTimeout(() => {
|
|
49
|
+
socket.terminate();
|
|
50
|
+
reject(new SessionError(`Timed out after ${timeoutMs} ms waiting for the ClientDevBridge handshake on ${url}.`));
|
|
51
|
+
}, timeoutMs);
|
|
52
|
+
socket.once('error', (error) => {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
const reason = error.code === 'ECONNREFUSED'
|
|
55
|
+
? `Nothing is listening on ${url}.`
|
|
56
|
+
: `Could not connect to ${url}: ${error.message}`;
|
|
57
|
+
reject(new SessionError(reason));
|
|
58
|
+
});
|
|
59
|
+
socket.on('message', function onMessage(raw) {
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = JSON.parse(String(raw));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const notification = rpcNotificationSchema.safeParse(parsed);
|
|
68
|
+
if (!notification.success) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (notification.data.method !== 'hello') {
|
|
72
|
+
early.push({ method: notification.data.method, params: notification.data.params });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
socket.off('message', onMessage);
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
const helloResult = helloSchema.safeParse(notification.data.params);
|
|
78
|
+
if (!helloResult.success) {
|
|
79
|
+
reject(new SessionError(`The client sent a handshake this CLI cannot read: ${helloResult.error.message}`));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
resolve(helloResult.data);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
if (hello.protocol !== SUPPORTED_PROTOCOL) {
|
|
86
|
+
socket.close();
|
|
87
|
+
const direction = hello.protocol > SUPPORTED_PROTOCOL ? 'update the CLI' : 'update the mod';
|
|
88
|
+
throw new SessionError(`Protocol mismatch: this CLI speaks protocol ${SUPPORTED_PROTOCOL}, the ClientDevBridge mod speaks ${hello.protocol}. Please ${direction}.`, hello.protocol > SUPPORTED_PROTOCOL
|
|
89
|
+
? 'npm install -g cyclops-clientdevbridge-cli@latest'
|
|
90
|
+
: 'Rebuild the ClientDevBridge mod, or pass --clientdevbridge-version to pick a matching build.');
|
|
91
|
+
}
|
|
92
|
+
const client = new BridgeClient(socket, hello);
|
|
93
|
+
if (options.onNotification !== undefined) {
|
|
94
|
+
client.onNotification(options.onNotification);
|
|
95
|
+
for (const notification of early) {
|
|
96
|
+
options.onNotification(notification.method, notification.params);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return client;
|
|
100
|
+
}
|
|
101
|
+
onNotification(listener) {
|
|
102
|
+
this.listeners.push(listener);
|
|
103
|
+
}
|
|
104
|
+
async call(method, params = {}, timeoutMs = 120_000) {
|
|
105
|
+
if (this.closedReason !== null) {
|
|
106
|
+
throw new SessionError(this.closedReason);
|
|
107
|
+
}
|
|
108
|
+
const id = this.nextId++;
|
|
109
|
+
const message = JSON.stringify({ jsonrpc: '2.0', id, method, params });
|
|
110
|
+
return new Promise((resolve, reject) => {
|
|
111
|
+
const timer = setTimeout(() => {
|
|
112
|
+
this.pending.delete(id);
|
|
113
|
+
reject(new SessionError(`'${method}' did not answer within ${timeoutMs} ms.`));
|
|
114
|
+
}, timeoutMs);
|
|
115
|
+
this.pending.set(id, {
|
|
116
|
+
resolve: (value) => {
|
|
117
|
+
clearTimeout(timer);
|
|
118
|
+
resolve(value);
|
|
119
|
+
},
|
|
120
|
+
reject: (error) => {
|
|
121
|
+
clearTimeout(timer);
|
|
122
|
+
reject(error);
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
this.socket.send(message);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
onMessage(raw) {
|
|
129
|
+
let parsed;
|
|
130
|
+
try {
|
|
131
|
+
parsed = JSON.parse(raw);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const response = rpcResponseSchema.safeParse(parsed);
|
|
137
|
+
if (response.success && response.data.id !== null) {
|
|
138
|
+
const pending = this.pending.get(Number(response.data.id));
|
|
139
|
+
if (pending === undefined) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this.pending.delete(Number(response.data.id));
|
|
143
|
+
if (response.data.error !== undefined) {
|
|
144
|
+
pending.reject(new ProtocolError(response.data.error.code, response.data.error.message, response.data.error.data));
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
pending.resolve(response.data.result ?? {});
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const notification = rpcNotificationSchema.safeParse(parsed);
|
|
152
|
+
if (notification.success) {
|
|
153
|
+
for (const listener of this.listeners) {
|
|
154
|
+
listener(notification.data.method, notification.data.params);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
failAll(reason) {
|
|
159
|
+
this.closedReason = reason;
|
|
160
|
+
for (const pending of this.pending.values()) {
|
|
161
|
+
pending.reject(new SessionError(reason));
|
|
162
|
+
}
|
|
163
|
+
this.pending.clear();
|
|
164
|
+
}
|
|
165
|
+
close() {
|
|
166
|
+
this.closedReason = this.closedReason ?? 'Connection closed by the CLI.';
|
|
167
|
+
this.socket.close();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/protocol/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** The protocol version this CLI speaks. Bumped only by a breaking change landed on every branch. */
|
|
3
|
+
export declare const SUPPORTED_PROTOCOL = 1;
|
|
4
|
+
export declare const helloSchema: z.ZodObject<{
|
|
5
|
+
protocol: z.ZodNumber;
|
|
6
|
+
mcVersion: z.ZodString;
|
|
7
|
+
loader: z.ZodString;
|
|
8
|
+
clientDevBridgeVersion: z.ZodString;
|
|
9
|
+
evalEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
+
/** The project this client was launched for; absent on an older bridge build. */
|
|
11
|
+
projectDir: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
12
|
+
mods: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
protocol: number;
|
|
15
|
+
mcVersion: string;
|
|
16
|
+
loader: string;
|
|
17
|
+
clientDevBridgeVersion: string;
|
|
18
|
+
mods: string[];
|
|
19
|
+
evalEnabled?: boolean | undefined;
|
|
20
|
+
projectDir?: string | null | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
protocol: number;
|
|
23
|
+
mcVersion: string;
|
|
24
|
+
loader: string;
|
|
25
|
+
clientDevBridgeVersion: string;
|
|
26
|
+
evalEnabled?: boolean | undefined;
|
|
27
|
+
projectDir?: string | null | undefined;
|
|
28
|
+
mods?: string[] | undefined;
|
|
29
|
+
}>;
|
|
30
|
+
export type Hello = z.infer<typeof helloSchema>;
|
|
31
|
+
export declare const rpcErrorSchema: z.ZodObject<{
|
|
32
|
+
code: z.ZodNumber;
|
|
33
|
+
message: z.ZodString;
|
|
34
|
+
data: z.ZodOptional<z.ZodUnknown>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
code: number;
|
|
37
|
+
message: string;
|
|
38
|
+
data?: unknown;
|
|
39
|
+
}, {
|
|
40
|
+
code: number;
|
|
41
|
+
message: string;
|
|
42
|
+
data?: unknown;
|
|
43
|
+
}>;
|
|
44
|
+
export declare const rpcResponseSchema: z.ZodObject<{
|
|
45
|
+
jsonrpc: z.ZodLiteral<"2.0">;
|
|
46
|
+
id: z.ZodUnion<[z.ZodNumber, z.ZodString, z.ZodNull]>;
|
|
47
|
+
result: z.ZodOptional<z.ZodUnknown>;
|
|
48
|
+
error: z.ZodOptional<z.ZodObject<{
|
|
49
|
+
code: z.ZodNumber;
|
|
50
|
+
message: z.ZodString;
|
|
51
|
+
data: z.ZodOptional<z.ZodUnknown>;
|
|
52
|
+
}, "strip", z.ZodTypeAny, {
|
|
53
|
+
code: number;
|
|
54
|
+
message: string;
|
|
55
|
+
data?: unknown;
|
|
56
|
+
}, {
|
|
57
|
+
code: number;
|
|
58
|
+
message: string;
|
|
59
|
+
data?: unknown;
|
|
60
|
+
}>>;
|
|
61
|
+
}, "strip", z.ZodTypeAny, {
|
|
62
|
+
jsonrpc: "2.0";
|
|
63
|
+
id: string | number | null;
|
|
64
|
+
result?: unknown;
|
|
65
|
+
error?: {
|
|
66
|
+
code: number;
|
|
67
|
+
message: string;
|
|
68
|
+
data?: unknown;
|
|
69
|
+
} | undefined;
|
|
70
|
+
}, {
|
|
71
|
+
jsonrpc: "2.0";
|
|
72
|
+
id: string | number | null;
|
|
73
|
+
result?: unknown;
|
|
74
|
+
error?: {
|
|
75
|
+
code: number;
|
|
76
|
+
message: string;
|
|
77
|
+
data?: unknown;
|
|
78
|
+
} | undefined;
|
|
79
|
+
}>;
|
|
80
|
+
export declare const rpcNotificationSchema: z.ZodObject<{
|
|
81
|
+
jsonrpc: z.ZodLiteral<"2.0">;
|
|
82
|
+
method: z.ZodString;
|
|
83
|
+
params: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
84
|
+
}, "strip", z.ZodTypeAny, {
|
|
85
|
+
params: Record<string, unknown>;
|
|
86
|
+
jsonrpc: "2.0";
|
|
87
|
+
method: string;
|
|
88
|
+
}, {
|
|
89
|
+
jsonrpc: "2.0";
|
|
90
|
+
method: string;
|
|
91
|
+
params?: Record<string, unknown> | undefined;
|
|
92
|
+
}>;
|
|
93
|
+
/** The metrics block every screenshot and snapshot result carries. */
|
|
94
|
+
export declare const metricsSchema: z.ZodObject<{
|
|
95
|
+
guiScale: z.ZodNumber;
|
|
96
|
+
guiWidth: z.ZodNumber;
|
|
97
|
+
guiHeight: z.ZodNumber;
|
|
98
|
+
pixelWidth: z.ZodNumber;
|
|
99
|
+
pixelHeight: z.ZodNumber;
|
|
100
|
+
}, "strip", z.ZodTypeAny, {
|
|
101
|
+
guiScale: number;
|
|
102
|
+
guiWidth: number;
|
|
103
|
+
guiHeight: number;
|
|
104
|
+
pixelWidth: number;
|
|
105
|
+
pixelHeight: number;
|
|
106
|
+
}, {
|
|
107
|
+
guiScale: number;
|
|
108
|
+
guiWidth: number;
|
|
109
|
+
guiHeight: number;
|
|
110
|
+
pixelWidth: number;
|
|
111
|
+
pixelHeight: number;
|
|
112
|
+
}>;
|
|
113
|
+
export type Metrics = z.infer<typeof metricsSchema>;
|
|
114
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/protocol/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,qGAAqG;AACrG,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,eAAO,MAAM,WAAW;;;;;;IAMtB,iFAAiF;;;;;;;;;;;;;;;;;;;EAGjF,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,cAAc;;;;;;;;;;;;EAIzB,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK5B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAIhC,CAAC;AAEH,sEAAsE;AACtE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;EAMxB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** The protocol version this CLI speaks. Bumped only by a breaking change landed on every branch. */
|
|
3
|
+
export const SUPPORTED_PROTOCOL = 1;
|
|
4
|
+
export const helloSchema = z.object({
|
|
5
|
+
protocol: z.number().int(),
|
|
6
|
+
mcVersion: z.string(),
|
|
7
|
+
loader: z.string(),
|
|
8
|
+
clientDevBridgeVersion: z.string(),
|
|
9
|
+
evalEnabled: z.boolean().optional(),
|
|
10
|
+
/** The project this client was launched for; absent on an older bridge build. */
|
|
11
|
+
projectDir: z.string().nullish(),
|
|
12
|
+
mods: z.array(z.string()).default([]),
|
|
13
|
+
});
|
|
14
|
+
export const rpcErrorSchema = z.object({
|
|
15
|
+
code: z.number().int(),
|
|
16
|
+
message: z.string(),
|
|
17
|
+
data: z.unknown().optional(),
|
|
18
|
+
});
|
|
19
|
+
export const rpcResponseSchema = z.object({
|
|
20
|
+
jsonrpc: z.literal('2.0'),
|
|
21
|
+
id: z.union([z.number(), z.string(), z.null()]),
|
|
22
|
+
result: z.unknown().optional(),
|
|
23
|
+
error: rpcErrorSchema.optional(),
|
|
24
|
+
});
|
|
25
|
+
export const rpcNotificationSchema = z.object({
|
|
26
|
+
jsonrpc: z.literal('2.0'),
|
|
27
|
+
method: z.string(),
|
|
28
|
+
params: z.record(z.unknown()).default({}),
|
|
29
|
+
});
|
|
30
|
+
/** The metrics block every screenshot and snapshot result carries. */
|
|
31
|
+
export const metricsSchema = z.object({
|
|
32
|
+
guiScale: z.number(),
|
|
33
|
+
guiWidth: z.number(),
|
|
34
|
+
guiHeight: z.number(),
|
|
35
|
+
pixelWidth: z.number(),
|
|
36
|
+
pixelHeight: z.number(),
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/protocol/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,qGAAqG;AACrG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE;IAClC,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnC,iFAAiF;IACjF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAChC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACtC,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACtB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACzB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/C,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,cAAc,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAC1C,CAAC,CAAC;AAEH,sEAAsE;AACtE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type BridgePaths } from './paths.js';
|
|
3
|
+
export declare const sessionSchema: z.ZodObject<{
|
|
4
|
+
version: z.ZodLiteral<1>;
|
|
5
|
+
port: z.ZodNumber;
|
|
6
|
+
pid: z.ZodNumber;
|
|
7
|
+
pgid: z.ZodNumber;
|
|
8
|
+
loader: z.ZodEnum<["fabric", "neoforge"]>;
|
|
9
|
+
mcVersion: z.ZodString;
|
|
10
|
+
bridgeVersion: z.ZodString;
|
|
11
|
+
projectDir: z.ZodString;
|
|
12
|
+
gradleTask: z.ZodString;
|
|
13
|
+
startedAt: z.ZodString;
|
|
14
|
+
world: z.ZodNullable<z.ZodString>;
|
|
15
|
+
headed: z.ZodBoolean;
|
|
16
|
+
display: z.ZodNullable<z.ZodString>;
|
|
17
|
+
jdwpPort: z.ZodNullable<z.ZodNumber>;
|
|
18
|
+
/**
|
|
19
|
+
* Xvfb servers this launch started. `stop` kills them explicitly: killing the process group
|
|
20
|
+
* does not reliably take them with it, and a leaked one is not harmless -- a stale server on a
|
|
21
|
+
* display a later run reuses makes the next client die with an X GLX BadAccess before it
|
|
22
|
+
* renders anything. Optional so a session file written by an older CLI still parses.
|
|
23
|
+
*/
|
|
24
|
+
xvfbPids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
|
|
25
|
+
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
mcVersion: string;
|
|
27
|
+
loader: "fabric" | "neoforge";
|
|
28
|
+
projectDir: string;
|
|
29
|
+
version: 1;
|
|
30
|
+
port: number;
|
|
31
|
+
pid: number;
|
|
32
|
+
pgid: number;
|
|
33
|
+
bridgeVersion: string;
|
|
34
|
+
gradleTask: string;
|
|
35
|
+
startedAt: string;
|
|
36
|
+
world: string | null;
|
|
37
|
+
headed: boolean;
|
|
38
|
+
display: string | null;
|
|
39
|
+
jdwpPort: number | null;
|
|
40
|
+
xvfbPids?: number[] | undefined;
|
|
41
|
+
}, {
|
|
42
|
+
mcVersion: string;
|
|
43
|
+
loader: "fabric" | "neoforge";
|
|
44
|
+
projectDir: string;
|
|
45
|
+
version: 1;
|
|
46
|
+
port: number;
|
|
47
|
+
pid: number;
|
|
48
|
+
pgid: number;
|
|
49
|
+
bridgeVersion: string;
|
|
50
|
+
gradleTask: string;
|
|
51
|
+
startedAt: string;
|
|
52
|
+
world: string | null;
|
|
53
|
+
headed: boolean;
|
|
54
|
+
display: string | null;
|
|
55
|
+
jdwpPort: number | null;
|
|
56
|
+
xvfbPids?: number[] | undefined;
|
|
57
|
+
}>;
|
|
58
|
+
export type Session = z.infer<typeof sessionSchema>;
|
|
59
|
+
export interface SessionStatus {
|
|
60
|
+
readonly paths: BridgePaths;
|
|
61
|
+
readonly session: Session | null;
|
|
62
|
+
/** True when session.json exists but the process it names is gone (a reclaimed VM, a crash, a reboot). */
|
|
63
|
+
readonly stale: boolean;
|
|
64
|
+
}
|
|
65
|
+
export declare function readSession(projectDir: string): SessionStatus;
|
|
66
|
+
export declare function writeSession(paths: BridgePaths, session: Session): void;
|
|
67
|
+
export declare function clearSession(paths: BridgePaths): void;
|
|
68
|
+
/**
|
|
69
|
+
* Returns the session for commands that need a running client, with a message that says what to do
|
|
70
|
+
* rather than just what went wrong.
|
|
71
|
+
*/
|
|
72
|
+
export declare function requireRunningSession(projectDir: string): {
|
|
73
|
+
session: Session;
|
|
74
|
+
paths: BridgePaths;
|
|
75
|
+
};
|
|
76
|
+
export declare function isProcessAlive(pid: number): boolean;
|
|
77
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,YAAY,CAAC;AAE5D,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;IAexB;;;;;OAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,0GAA0G;IAC1G,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAgB7D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAEvE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAIrD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAqBlG;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQnD"}
|