@serverkgg/bridge 0.0.3 → 0.0.5
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/README.md +1 -1
- package/package.json +1 -1
- package/src/cli/compile.ts +19 -37
- package/src/cli/main.ts +1 -1
- package/src/core/bridgePort.ts +5 -0
- package/src/manifest/manifest.test.ts +104 -0
- package/src/manifest/manifest.ts +21 -1
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ bunx serverk-bridge validate
|
|
|
41
41
|
bunx serverk-bridge compile
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
`validate` checks `serverk.yml` against the real platform schema, verifies the logo and banner, and validates the driver's panel wiring. `compile` produces `dist/bridge
|
|
44
|
+
`validate` checks `serverk.yml` against the real platform schema, verifies the logo and banner, and validates the driver's panel wiring. `compile` produces `dist/bridge`, an amd64 binary — serverk publishes game images for `linux/amd64` only.
|
|
45
45
|
|
|
46
46
|
## Compatibility
|
|
47
47
|
|
package/package.json
CHANGED
package/src/cli/compile.ts
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { parseArgs } from "node:util";
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
amd64: "bun-linux-x64",
|
|
5
|
-
arm64: "bun-linux-arm64",
|
|
6
|
-
};
|
|
3
|
+
const TARGET = "bun-linux-x64";
|
|
7
4
|
|
|
8
5
|
const HELP = `serverk-bridge compile [options]
|
|
9
6
|
|
|
10
7
|
options:
|
|
11
|
-
--arch <amd64|arm64> architecture to compile (repeatable, default: both)
|
|
12
8
|
--entry <path> entrypoint (default: src/main.ts)
|
|
13
9
|
--outdir <path> output directory (default: dist)
|
|
14
10
|
--help show this help`;
|
|
@@ -17,10 +13,6 @@ export const runCompile = async (args: string[]) => {
|
|
|
17
13
|
const { values } = parseArgs({
|
|
18
14
|
args,
|
|
19
15
|
options: {
|
|
20
|
-
arch: {
|
|
21
|
-
type: "string",
|
|
22
|
-
multiple: true,
|
|
23
|
-
},
|
|
24
16
|
entry: {
|
|
25
17
|
type: "string",
|
|
26
18
|
default: "src/main.ts",
|
|
@@ -42,34 +34,24 @@ export const runCompile = async (args: string[]) => {
|
|
|
42
34
|
return;
|
|
43
35
|
}
|
|
44
36
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
values.entry,
|
|
62
|
-
"--outfile",
|
|
63
|
-
outfile,
|
|
64
|
-
],
|
|
65
|
-
{
|
|
66
|
-
stderr: "inherit",
|
|
67
|
-
stdout: "inherit",
|
|
68
|
-
},
|
|
69
|
-
);
|
|
37
|
+
const outfile = `${values.outdir}/bridge`;
|
|
38
|
+
const child = Bun.spawn(
|
|
39
|
+
[
|
|
40
|
+
"bun",
|
|
41
|
+
"build",
|
|
42
|
+
"--compile",
|
|
43
|
+
`--target=${TARGET}`,
|
|
44
|
+
values.entry,
|
|
45
|
+
"--outfile",
|
|
46
|
+
outfile,
|
|
47
|
+
],
|
|
48
|
+
{
|
|
49
|
+
stderr: "inherit",
|
|
50
|
+
stdout: "inherit",
|
|
51
|
+
},
|
|
52
|
+
);
|
|
70
53
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
54
|
+
if ((await child.exited) !== 0) {
|
|
55
|
+
throw new Error("compile failed");
|
|
74
56
|
}
|
|
75
57
|
};
|
package/src/cli/main.ts
CHANGED
|
@@ -11,7 +11,7 @@ const USAGE = `serverk-bridge <command>
|
|
|
11
11
|
commands:
|
|
12
12
|
validate validate serverk.yml, assets, and driver wiring
|
|
13
13
|
schema write the serverk.yml JSON Schema for editor tooling
|
|
14
|
-
compile compile the bridge binary for amd64
|
|
14
|
+
compile compile the bridge binary for amd64
|
|
15
15
|
link use a local bridge checkout while developing
|
|
16
16
|
|
|
17
17
|
run "serverk-bridge <command> --help" for options`;
|
package/src/core/bridgePort.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { PortJoin } from "../core";
|
|
3
4
|
import { GameCategory } from "./category";
|
|
4
5
|
import { guidePackageSchema, MANIFEST_SCHEMA_VERSION, manifestSchema, packageSchema } from "./manifest";
|
|
5
6
|
|
|
@@ -55,6 +56,34 @@ const failure = (input: unknown) => {
|
|
|
55
56
|
}));
|
|
56
57
|
};
|
|
57
58
|
|
|
59
|
+
const withPort = (extra: Record<string, unknown>) => {
|
|
60
|
+
const manifest = base();
|
|
61
|
+
const [game] = manifest.container.ports;
|
|
62
|
+
|
|
63
|
+
if (!game) {
|
|
64
|
+
throw new Error("fixture is missing its port");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
...manifest,
|
|
69
|
+
container: {
|
|
70
|
+
...manifest.container,
|
|
71
|
+
ports: [
|
|
72
|
+
{
|
|
73
|
+
...game,
|
|
74
|
+
...extra,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const withPortSrv = (srv: unknown) => {
|
|
82
|
+
return withPort({
|
|
83
|
+
srv,
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
58
87
|
describe("defaults", () => {
|
|
59
88
|
test("fills in the optional sections so consumers never guard", () => {
|
|
60
89
|
const manifest = manifestSchema.parse(base());
|
|
@@ -72,6 +101,81 @@ describe("defaults", () => {
|
|
|
72
101
|
});
|
|
73
102
|
expect(manifest.guides).toEqual([]);
|
|
74
103
|
expect(manifest.secrets).toEqual([]);
|
|
104
|
+
expect(manifest.container.ports[0]?.srv).toBeUndefined();
|
|
105
|
+
expect(manifest.container.ports[0]?.name).toBeUndefined();
|
|
106
|
+
expect(manifest.container.ports[0]?.hint).toBeUndefined();
|
|
107
|
+
expect(manifest.container.ports[0]?.join).toBe(PortJoin.Combined);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe("port presentation", () => {
|
|
112
|
+
test("keeps the localized name, hint and join style a port declares", () => {
|
|
113
|
+
const manifest = manifestSchema.parse(
|
|
114
|
+
withPort({
|
|
115
|
+
name: {
|
|
116
|
+
ar: "بيدروك",
|
|
117
|
+
en: "Bedrock",
|
|
118
|
+
},
|
|
119
|
+
hint: {
|
|
120
|
+
ar: "العنوان في خانة والمنفذ في خانة ثانية",
|
|
121
|
+
en: "Address and port go in separate fields",
|
|
122
|
+
},
|
|
123
|
+
join: "separate",
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
expect(manifest.container.ports[0]?.name).toEqual({
|
|
128
|
+
ar: "بيدروك",
|
|
129
|
+
en: "Bedrock",
|
|
130
|
+
});
|
|
131
|
+
expect(manifest.container.ports[0]?.hint?.en).toBe("Address and port go in separate fields");
|
|
132
|
+
expect(manifest.container.ports[0]?.join).toBe(PortJoin.Separate);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("rejects a port name missing one language", () => {
|
|
136
|
+
expect(
|
|
137
|
+
failure(
|
|
138
|
+
withPort({
|
|
139
|
+
name: {
|
|
140
|
+
en: "Bedrock",
|
|
141
|
+
},
|
|
142
|
+
}),
|
|
143
|
+
),
|
|
144
|
+
).toEqual([
|
|
145
|
+
{
|
|
146
|
+
path: "container.ports.0.name.ar",
|
|
147
|
+
message: "Invalid input: expected string, received undefined",
|
|
148
|
+
},
|
|
149
|
+
]);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("port srv", () => {
|
|
154
|
+
test("keeps the service label a port declares", () => {
|
|
155
|
+
const manifest = manifestSchema.parse(
|
|
156
|
+
withPortSrv({
|
|
157
|
+
service: "_minecraft",
|
|
158
|
+
}),
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
expect(manifest.container.ports[0]?.srv).toEqual({
|
|
162
|
+
service: "_minecraft",
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("rejects a service label without its underscore", () => {
|
|
167
|
+
expect(
|
|
168
|
+
failure(
|
|
169
|
+
withPortSrv({
|
|
170
|
+
service: "minecraft",
|
|
171
|
+
}),
|
|
172
|
+
),
|
|
173
|
+
).toEqual([
|
|
174
|
+
{
|
|
175
|
+
path: "container.ports.0.srv.service",
|
|
176
|
+
message: "must be an underscore-prefixed service label such as _minecraft",
|
|
177
|
+
},
|
|
178
|
+
]);
|
|
75
179
|
});
|
|
76
180
|
});
|
|
77
181
|
|
package/src/manifest/manifest.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { PortProtocol } from "../core";
|
|
2
|
+
import { PortJoin, PortProtocol } from "../core";
|
|
3
3
|
import { BridgeIcon } from "../panel/bridgeIcon";
|
|
4
4
|
import { GameCategory } from "./category";
|
|
5
5
|
import { type GuideEntry, type GuideTag, guideEntrySchema, guideTagSchema } from "./guide";
|
|
@@ -43,6 +43,26 @@ const manifestPortSchema = z.object({
|
|
|
43
43
|
containerPort: zPort,
|
|
44
44
|
protocol: z.enum(PortProtocol).default(PortProtocol.Tcp),
|
|
45
45
|
hostRange: manifestHostRangeSchema,
|
|
46
|
+
name: localizedText(48).optional().meta({
|
|
47
|
+
description: "Player-facing name of this port, such as Java or Bedrock. The key is shown when omitted.",
|
|
48
|
+
}),
|
|
49
|
+
hint: localizedText(160).optional().meta({
|
|
50
|
+
description: "One short line telling the player where this address goes in the game client.",
|
|
51
|
+
}),
|
|
52
|
+
join: z.enum(PortJoin).default(PortJoin.Combined).meta({
|
|
53
|
+
description: "How the game client takes the address: combined as host:port, or separate address and port fields.",
|
|
54
|
+
}),
|
|
55
|
+
srv: z
|
|
56
|
+
.object({
|
|
57
|
+
service: z
|
|
58
|
+
.string()
|
|
59
|
+
.regex(/^_[a-z0-9-]{1,15}$/, "must be an underscore-prefixed service label such as _minecraft"),
|
|
60
|
+
})
|
|
61
|
+
.optional()
|
|
62
|
+
.meta({
|
|
63
|
+
description:
|
|
64
|
+
"Publishes this port as an SRV record under the server hostname, so players join by name with no port.",
|
|
65
|
+
}),
|
|
46
66
|
});
|
|
47
67
|
|
|
48
68
|
export type ManifestPort = z.infer<typeof manifestPortSchema>;
|