@serverkgg/bridge 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/cli/validate.ts +2 -0
- package/src/context/bridgeContext.ts +17 -0
- package/src/context/index.ts +1 -0
- package/src/core/bridgeDownloadError.ts +10 -0
- package/src/core/bridgeHold.ts +12 -0
- package/src/core/bridgeKind.ts +3 -0
- package/src/core/bridgeProbeError.ts +16 -0
- package/src/core/bridgeSetup.ts +20 -0
- package/src/core/bridgeUserError.test.ts +23 -0
- package/src/core/bridgeUserError.ts +12 -0
- package/src/core/bridgeValue.test.ts +29 -0
- package/src/core/bridgeValue.ts +12 -0
- package/src/core/index.ts +5 -0
- package/src/guides/blocks.ts +8 -0
- package/src/guides/markdown.test.ts +18 -0
- package/src/guides/markdown.ts +7 -1
- package/src/manifest/index.ts +1 -0
- package/src/manifest/manifest.test.ts +132 -0
- package/src/manifest/manifest.ts +21 -0
- package/src/manifest/presence.ts +56 -0
- package/src/manifest/primitives.ts +6 -0
- package/src/modules/bridge.ts +65 -2
- package/src/modules/bridgeDriver.ts +4 -0
- package/src/modules/bridgeModule.ts +32 -3
- package/src/panel/bridgeDetail.ts +49 -0
- package/src/panel/bridgeLayout.ts +1 -0
- package/src/panel/bridgePanel.ts +30 -0
- package/src/panel/bridgeUploadMode.ts +4 -0
- package/src/panel/index.ts +2 -0
- package/src/probes/a2s.test.ts +71 -0
- package/src/probes/a2s.ts +38 -11
- package/src/protocol/bridgeEgress.ts +8 -1
- package/src/protocol/bridgeEvents.ts +4 -0
- package/src/protocol/bridgeFrame.ts +33 -1
- package/src/protocol/bridgeLimits.ts +12 -0
- package/src/protocol/bridgeManifest.ts +2 -0
- package/src/protocol/bridgeSetup.ts +97 -0
- package/src/protocol/index.ts +1 -0
- package/src/runtime/bridgeActions.ts +7 -0
- package/src/runtime/bridgeConfigReader.ts +12 -8
- package/src/runtime/bridgeContext.ts +28 -2
- package/src/runtime/bridgeDriver.test.ts +748 -3
- package/src/runtime/bridgeDriver.ts +198 -4
- package/src/runtime/bridgeEgress.ts +3 -0
- package/src/runtime/bridgeEvents.test.ts +96 -0
- package/src/runtime/bridgeEvents.ts +11 -6
- package/src/runtime/bridgeFiles.test.ts +625 -15
- package/src/runtime/bridgeFiles.ts +152 -45
- package/src/runtime/bridgeInstall.test.ts +118 -0
- package/src/runtime/bridgeInstall.ts +55 -0
- package/src/runtime/bridgeNet.ts +32 -3
- package/src/runtime/bridgePending.test.ts +148 -0
- package/src/runtime/bridgePending.ts +43 -0
- package/src/runtime/bridgeRegistry.test.ts +172 -1
- package/src/runtime/bridgeRegistry.ts +40 -5
- package/src/runtime/bridgeSecrets.test.ts +121 -0
- package/src/runtime/bridgeSecrets.ts +43 -0
- package/src/runtime/bridgeServer.test.ts +598 -0
- package/src/runtime/bridgeServer.ts +42 -3
- package/src/runtime/bridgeSetup.test.ts +189 -0
- package/src/runtime/bridgeSetup.ts +63 -0
- package/src/runtime/bridgeSignal.test.ts +114 -0
- package/src/runtime/bridgeSignal.ts +31 -0
- package/src/runtime/bridgeSupervisor.test.ts +111 -0
- package/src/runtime/bridgeSupervisor.ts +55 -5
- package/src/runtime/bridgeZip.ts +179 -58
- package/src/runtime/serve.ts +115 -4
- package/src/utils/index.ts +1 -0
- package/src/utils/stripAnsi.ts +12 -0
- package/src/wire/panel.test.ts +259 -0
- package/src/wire/panel.ts +72 -0
package/src/wire/panel.test.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { GuideOpenTab } from "@serverkgg/bridge/guides";
|
|
2
3
|
import {
|
|
3
4
|
BridgeAccess,
|
|
4
5
|
BridgeAction,
|
|
@@ -8,6 +9,9 @@ import {
|
|
|
8
9
|
BridgeKind,
|
|
9
10
|
BridgeLayout,
|
|
10
11
|
type BridgeManifest,
|
|
12
|
+
type BridgeSetupManifest,
|
|
13
|
+
BridgeSetupStepKind,
|
|
14
|
+
BridgeUploadMode,
|
|
11
15
|
} from "@serverkgg/bridge/protocol";
|
|
12
16
|
import { bridgeManifestSchema } from "./panel";
|
|
13
17
|
|
|
@@ -97,6 +101,7 @@ const manifest = (): BridgeManifest => ({
|
|
|
97
101
|
],
|
|
98
102
|
},
|
|
99
103
|
terminal: null,
|
|
104
|
+
setup: null,
|
|
100
105
|
modules: [
|
|
101
106
|
{
|
|
102
107
|
id: "broadcast",
|
|
@@ -158,6 +163,7 @@ const previewManifest = (): BridgeManifest => ({
|
|
|
158
163
|
],
|
|
159
164
|
},
|
|
160
165
|
terminal: null,
|
|
166
|
+
setup: null,
|
|
161
167
|
modules: [
|
|
162
168
|
{
|
|
163
169
|
id: "transition",
|
|
@@ -283,3 +289,256 @@ describe("the panel mirror", () => {
|
|
|
283
289
|
).toBe(false);
|
|
284
290
|
});
|
|
285
291
|
});
|
|
292
|
+
|
|
293
|
+
const detailManifest = (): BridgeManifest => ({
|
|
294
|
+
version: "1.0.0",
|
|
295
|
+
panel: {
|
|
296
|
+
tabs: [
|
|
297
|
+
{
|
|
298
|
+
id: "version",
|
|
299
|
+
title: text("Version"),
|
|
300
|
+
sections: [
|
|
301
|
+
{
|
|
302
|
+
layout: BridgeLayout.Form,
|
|
303
|
+
id: "version",
|
|
304
|
+
target: BridgeFormTarget.Variables,
|
|
305
|
+
reinstall: true,
|
|
306
|
+
fields: [
|
|
307
|
+
{
|
|
308
|
+
key: "MC_VERSION",
|
|
309
|
+
control: BridgeControl.Text,
|
|
310
|
+
label: text("Version"),
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
clears: [
|
|
314
|
+
{
|
|
315
|
+
variable: "MODPACK",
|
|
316
|
+
warning: text("Applying this removes the modpack"),
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
layout: BridgeLayout.Detail,
|
|
322
|
+
id: "modpack-status",
|
|
323
|
+
title: text("Running a modpack"),
|
|
324
|
+
module: "modpackStatus",
|
|
325
|
+
reinstall: true,
|
|
326
|
+
variable: "MODPACK",
|
|
327
|
+
confirm: BridgeConfirm.Strong,
|
|
328
|
+
related: {
|
|
329
|
+
tab: "modpacks",
|
|
330
|
+
label: text("Browse modpacks"),
|
|
331
|
+
},
|
|
332
|
+
actions: [
|
|
333
|
+
{
|
|
334
|
+
id: "update",
|
|
335
|
+
label: text("Update"),
|
|
336
|
+
confirm: BridgeConfirm.Strong,
|
|
337
|
+
},
|
|
338
|
+
],
|
|
339
|
+
},
|
|
340
|
+
],
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
},
|
|
344
|
+
terminal: null,
|
|
345
|
+
setup: null,
|
|
346
|
+
modules: [
|
|
347
|
+
{
|
|
348
|
+
id: "modpackStatus",
|
|
349
|
+
kind: BridgeKind.Detail,
|
|
350
|
+
requiresRunning: false,
|
|
351
|
+
refreshSeconds: null,
|
|
352
|
+
pageSize: null,
|
|
353
|
+
dependsOn: [],
|
|
354
|
+
actions: [
|
|
355
|
+
BridgeAction.Read,
|
|
356
|
+
"update",
|
|
357
|
+
],
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
events: [],
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
describe("detail sections", () => {
|
|
364
|
+
test("round-trips a detail section and a clearing form", () => {
|
|
365
|
+
const source = detailManifest();
|
|
366
|
+
|
|
367
|
+
expect(bridgeManifestSchema.parse(source)).toEqual(source);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
test("refuses a clear whose variable is not an env key", () => {
|
|
371
|
+
const source = detailManifest();
|
|
372
|
+
const [form] = source.panel?.tabs[0]?.sections ?? [];
|
|
373
|
+
|
|
374
|
+
if (form?.layout !== BridgeLayout.Form) {
|
|
375
|
+
throw new Error("fixture is missing its form section");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
form.clears = [
|
|
379
|
+
{
|
|
380
|
+
variable: "mod pack",
|
|
381
|
+
warning: text("Broken"),
|
|
382
|
+
},
|
|
383
|
+
];
|
|
384
|
+
|
|
385
|
+
expect(bridgeManifestSchema.safeParse(source).success).toBe(false);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
const uploadManifest = (mode?: BridgeUploadMode): BridgeManifest => ({
|
|
390
|
+
version: "1.0.0",
|
|
391
|
+
panel: {
|
|
392
|
+
tabs: [
|
|
393
|
+
{
|
|
394
|
+
id: "modpacks",
|
|
395
|
+
title: text("Modpacks"),
|
|
396
|
+
sections: [
|
|
397
|
+
{
|
|
398
|
+
layout: BridgeLayout.Table,
|
|
399
|
+
id: "pending",
|
|
400
|
+
module: "pending",
|
|
401
|
+
columns: [
|
|
402
|
+
{
|
|
403
|
+
key: "name",
|
|
404
|
+
label: text("Name"),
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
upload: {
|
|
408
|
+
label: text("Upload"),
|
|
409
|
+
extensions: [
|
|
410
|
+
"jar",
|
|
411
|
+
],
|
|
412
|
+
staging: ".serverk-staging/pending-upload",
|
|
413
|
+
mode,
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
],
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
},
|
|
420
|
+
terminal: null,
|
|
421
|
+
setup: null,
|
|
422
|
+
modules: [
|
|
423
|
+
{
|
|
424
|
+
id: "pending",
|
|
425
|
+
kind: BridgeKind.Collection,
|
|
426
|
+
requiresRunning: false,
|
|
427
|
+
refreshSeconds: null,
|
|
428
|
+
pageSize: null,
|
|
429
|
+
dependsOn: [],
|
|
430
|
+
actions: [],
|
|
431
|
+
},
|
|
432
|
+
],
|
|
433
|
+
events: [],
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
describe("the upload mirror", () => {
|
|
437
|
+
test("carries the file upload mode through unchanged", () => {
|
|
438
|
+
const source = uploadManifest(BridgeUploadMode.File);
|
|
439
|
+
const parsed = bridgeManifestSchema.parse(source);
|
|
440
|
+
const [section] = parsed.panel?.tabs[0]?.sections ?? [];
|
|
441
|
+
|
|
442
|
+
if (section?.layout !== BridgeLayout.Table) {
|
|
443
|
+
throw new Error("fixture is missing its table section");
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
expect(section.upload?.mode).toBe(BridgeUploadMode.File);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test("takes an upload that declares no mode", () => {
|
|
450
|
+
expect(bridgeManifestSchema.safeParse(uploadManifest()).success).toBe(true);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
test("refuses an upload mode the platform does not know", () => {
|
|
454
|
+
const source = uploadManifest("stream" as BridgeUploadMode);
|
|
455
|
+
|
|
456
|
+
expect(bridgeManifestSchema.safeParse(source).success).toBe(false);
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
const setupManifest = (setup: BridgeSetupManifest | null): BridgeManifest => ({
|
|
461
|
+
version: "1.0.0",
|
|
462
|
+
panel: null,
|
|
463
|
+
terminal: null,
|
|
464
|
+
setup,
|
|
465
|
+
modules: [],
|
|
466
|
+
events: [],
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
describe("the setup mirror", () => {
|
|
470
|
+
test("carries every step kind through unchanged", () => {
|
|
471
|
+
const source = setupManifest({
|
|
472
|
+
steps: [
|
|
473
|
+
{
|
|
474
|
+
kind: BridgeSetupStepKind.Driver,
|
|
475
|
+
id: "sign-in",
|
|
476
|
+
title: text("Sign in"),
|
|
477
|
+
help: text("Sign in with your account"),
|
|
478
|
+
requiresRunning: true,
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
kind: BridgeSetupStepKind.Form,
|
|
482
|
+
id: "name",
|
|
483
|
+
title: text("Name your server"),
|
|
484
|
+
required: false,
|
|
485
|
+
tab: "settings",
|
|
486
|
+
section: "server",
|
|
487
|
+
fields: [
|
|
488
|
+
"SERVER_NAME",
|
|
489
|
+
],
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
kind: BridgeSetupStepKind.Open,
|
|
493
|
+
id: "invite",
|
|
494
|
+
title: text("Invite your friends"),
|
|
495
|
+
target: {
|
|
496
|
+
tab: GuideOpenTab.Access,
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
],
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
expect(bridgeManifestSchema.parse(source).setup).toEqual(source.setup);
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
test("takes a manifest that declares no setup", () => {
|
|
506
|
+
expect(bridgeManifestSchema.parse(setupManifest(null)).setup).toBeNull();
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
test("defaults a manifest from an older bridge that carries no setup block to null", () => {
|
|
510
|
+
const older = setupManifest(null);
|
|
511
|
+
|
|
512
|
+
delete (older as Partial<BridgeManifest>).setup;
|
|
513
|
+
|
|
514
|
+
expect(bridgeManifestSchema.parse(older).setup).toBeNull();
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
test("refuses a step kind the platform does not know", () => {
|
|
518
|
+
const source = setupManifest({
|
|
519
|
+
steps: [
|
|
520
|
+
{
|
|
521
|
+
kind: "wizard" as BridgeSetupStepKind.Driver,
|
|
522
|
+
id: "sign-in",
|
|
523
|
+
title: text("Sign in"),
|
|
524
|
+
},
|
|
525
|
+
],
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
expect(bridgeManifestSchema.safeParse(source).success).toBe(false);
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
test("refuses more steps than the platform takes", () => {
|
|
532
|
+
const source = setupManifest({
|
|
533
|
+
steps: Array.from({
|
|
534
|
+
length: 9,
|
|
535
|
+
}).map((_entry, index) => ({
|
|
536
|
+
kind: BridgeSetupStepKind.Driver as const,
|
|
537
|
+
id: `step-${index}`,
|
|
538
|
+
title: text(`Step ${index}`),
|
|
539
|
+
})),
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
expect(bridgeManifestSchema.safeParse(source).success).toBe(false);
|
|
543
|
+
});
|
|
544
|
+
});
|
package/src/wire/panel.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { guideOpenTargetSchema } from "@serverkgg/bridge/guides";
|
|
1
2
|
import {
|
|
2
3
|
BRIDGE_ID_PATTERN,
|
|
3
4
|
BRIDGE_MODULE_ID_PATTERN,
|
|
@@ -11,12 +12,16 @@ import {
|
|
|
11
12
|
type BridgeManifest,
|
|
12
13
|
type BridgePanel,
|
|
13
14
|
type BridgeSection,
|
|
15
|
+
type BridgeSetupManifest,
|
|
16
|
+
type BridgeSetupStep,
|
|
17
|
+
BridgeSetupStepKind,
|
|
14
18
|
BridgeStream,
|
|
15
19
|
type BridgeTerminalArg,
|
|
16
20
|
type BridgeTerminalCommand,
|
|
17
21
|
BridgeTerminalLevel,
|
|
18
22
|
type BridgeTerminalManifest,
|
|
19
23
|
type BridgeTerminalRuleManifest,
|
|
24
|
+
BridgeUploadMode,
|
|
20
25
|
} from "@serverkgg/bridge/protocol";
|
|
21
26
|
import { z } from "zod";
|
|
22
27
|
import { zEnvKey } from "./zEnvKey";
|
|
@@ -27,6 +32,12 @@ const ACTION_FIELDS_LIMIT = 5;
|
|
|
27
32
|
|
|
28
33
|
const SECTION_ACTIONS_LIMIT = 10;
|
|
29
34
|
|
|
35
|
+
const FORM_CLEARS_LIMIT = 8;
|
|
36
|
+
|
|
37
|
+
const SETUP_STEPS_LIMIT = 8;
|
|
38
|
+
|
|
39
|
+
const SETUP_STEP_FIELDS_LIMIT = 32;
|
|
40
|
+
|
|
30
41
|
const zKey = z
|
|
31
42
|
.string()
|
|
32
43
|
.min(1)
|
|
@@ -107,6 +118,16 @@ export const bridgeSectionActionSchema = z.object({
|
|
|
107
118
|
fields: z.array(bridgeFieldSchema).max(ACTION_FIELDS_LIMIT).optional(),
|
|
108
119
|
});
|
|
109
120
|
|
|
121
|
+
export const bridgeTabRefSchema = z.object({
|
|
122
|
+
tab: zBridgeId,
|
|
123
|
+
label: panelTextSchema,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export const bridgeFormClearSchema = z.object({
|
|
127
|
+
variable: zEnvKey,
|
|
128
|
+
warning: panelTextSchema,
|
|
129
|
+
});
|
|
130
|
+
|
|
110
131
|
export const bridgeSectionAddSchema = z.object({
|
|
111
132
|
label: panelTextSchema,
|
|
112
133
|
placeholder: z.string().max(256).optional(),
|
|
@@ -116,6 +137,7 @@ export const bridgeSectionUploadSchema = z.object({
|
|
|
116
137
|
label: panelTextSchema,
|
|
117
138
|
extensions: z.array(z.string().min(1).max(16)).min(1).max(8),
|
|
118
139
|
staging: z.string().min(1).max(128),
|
|
140
|
+
mode: z.enum(BridgeUploadMode).optional(),
|
|
119
141
|
});
|
|
120
142
|
|
|
121
143
|
export const bridgeActionsSectionSchema = z.object({
|
|
@@ -141,6 +163,23 @@ export const bridgeFormSectionSchema = z.object({
|
|
|
141
163
|
confirm: z.enum(BridgeConfirm).optional(),
|
|
142
164
|
confirmText: panelTextSchema.optional(),
|
|
143
165
|
fields: z.array(bridgeFieldSchema).min(1).max(32),
|
|
166
|
+
clears: z.array(bridgeFormClearSchema).max(FORM_CLEARS_LIMIT).optional(),
|
|
167
|
+
visibleWhen: bridgeVisibleWhenSchema.optional(),
|
|
168
|
+
access: z.enum(BridgeAccess).optional(),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
export const bridgeDetailSectionSchema = z.object({
|
|
172
|
+
layout: z.literal(BridgeLayout.Detail),
|
|
173
|
+
id: zBridgeId,
|
|
174
|
+
title: panelTextSchema.optional(),
|
|
175
|
+
module: zBridgeModuleId,
|
|
176
|
+
actions: z.array(bridgeSectionActionSchema).max(SECTION_ACTIONS_LIMIT).optional(),
|
|
177
|
+
reinstall: z.boolean().optional(),
|
|
178
|
+
variable: zEnvKey.optional(),
|
|
179
|
+
confirm: z.enum(BridgeConfirm).optional(),
|
|
180
|
+
confirmText: panelTextSchema.optional(),
|
|
181
|
+
related: bridgeTabRefSchema.optional(),
|
|
182
|
+
empty: panelTextSchema.optional(),
|
|
144
183
|
visibleWhen: bridgeVisibleWhenSchema.optional(),
|
|
145
184
|
access: z.enum(BridgeAccess).optional(),
|
|
146
185
|
});
|
|
@@ -197,6 +236,7 @@ export const bridgeSectionSchema: z.ZodType<BridgeSection> = z.discriminatedUnio
|
|
|
197
236
|
bridgeActionsSectionSchema,
|
|
198
237
|
bridgeCardsSectionSchema,
|
|
199
238
|
bridgeCatalogSectionSchema,
|
|
239
|
+
bridgeDetailSectionSchema,
|
|
200
240
|
bridgeFormSectionSchema,
|
|
201
241
|
bridgeTableSectionSchema,
|
|
202
242
|
]);
|
|
@@ -244,6 +284,37 @@ export const bridgeTerminalManifestSchema: z.ZodType<BridgeTerminalManifest> = z
|
|
|
244
284
|
rules: z.array(bridgeTerminalRuleSchema).max(64),
|
|
245
285
|
});
|
|
246
286
|
|
|
287
|
+
const setupStepBase = {
|
|
288
|
+
id: zBridgeId,
|
|
289
|
+
title: panelTextSchema,
|
|
290
|
+
help: panelTextSchema.optional(),
|
|
291
|
+
required: z.boolean().optional(),
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export const bridgeSetupStepSchema: z.ZodType<BridgeSetupStep> = z.discriminatedUnion("kind", [
|
|
295
|
+
z.object({
|
|
296
|
+
...setupStepBase,
|
|
297
|
+
kind: z.literal(BridgeSetupStepKind.Driver),
|
|
298
|
+
requiresRunning: z.boolean().optional(),
|
|
299
|
+
}),
|
|
300
|
+
z.object({
|
|
301
|
+
...setupStepBase,
|
|
302
|
+
kind: z.literal(BridgeSetupStepKind.Form),
|
|
303
|
+
tab: zBridgeId,
|
|
304
|
+
section: zBridgeId,
|
|
305
|
+
fields: z.array(zKey).max(SETUP_STEP_FIELDS_LIMIT).optional(),
|
|
306
|
+
}),
|
|
307
|
+
z.object({
|
|
308
|
+
...setupStepBase,
|
|
309
|
+
kind: z.literal(BridgeSetupStepKind.Open),
|
|
310
|
+
target: guideOpenTargetSchema,
|
|
311
|
+
}),
|
|
312
|
+
]);
|
|
313
|
+
|
|
314
|
+
export const bridgeSetupManifestSchema: z.ZodType<BridgeSetupManifest> = z.object({
|
|
315
|
+
steps: z.array(bridgeSetupStepSchema).min(1).max(SETUP_STEPS_LIMIT),
|
|
316
|
+
});
|
|
317
|
+
|
|
247
318
|
export const bridgeModuleManifestSchema = z.object({
|
|
248
319
|
id: zBridgeModuleId,
|
|
249
320
|
kind: z.enum(BridgeKind),
|
|
@@ -258,6 +329,7 @@ export const bridgeManifestSchema: z.ZodType<BridgeManifest> = z.object({
|
|
|
258
329
|
version: z.string(),
|
|
259
330
|
panel: bridgePanelSchema.nullable(),
|
|
260
331
|
terminal: bridgeTerminalManifestSchema.nullable().default(null),
|
|
332
|
+
setup: bridgeSetupManifestSchema.nullable().default(null),
|
|
261
333
|
modules: z.array(bridgeModuleManifestSchema).max(32),
|
|
262
334
|
events: z.array(z.string().min(1).max(64)).max(32),
|
|
263
335
|
});
|