@zgeoff/imp-client 0.16.0 → 0.17.0
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 +42 -8
- package/dist/index.d.ts +1655 -73
- package/dist/index.js +376 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { RPCLink } from "@orpc/client/fetch";
|
|
|
3
3
|
import * as z from "zod";
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region src/check-server.ts
|
|
6
|
-
const CLIENT_VERSION = "0.
|
|
6
|
+
const CLIENT_VERSION = "0.17.0";
|
|
7
7
|
async function checkServer(rpc) {
|
|
8
8
|
const info = await rpc.system.info();
|
|
9
9
|
return {
|
|
@@ -28,6 +28,137 @@ function parseVersion(version) {
|
|
|
28
28
|
//#endregion
|
|
29
29
|
//#region ../api/src/name-schema.ts
|
|
30
30
|
const NameSchema = z.string().regex(/^[a-z][a-z0-9-]{0,30}$/, "must be a lowercase letter followed by up to 30 lowercase letters, digits or hyphens");
|
|
31
|
+
z.enum(["tailnet", "public"]);
|
|
32
|
+
const PublicAuthSchema = z.enum([
|
|
33
|
+
"none",
|
|
34
|
+
"token",
|
|
35
|
+
"basic"
|
|
36
|
+
]);
|
|
37
|
+
const BasicUserSchema = z.string().regex(/^[!-9;-~]{1,64}$/, "must be 1 to 64 printable characters, without a colon");
|
|
38
|
+
z.object({
|
|
39
|
+
name: NameSchema,
|
|
40
|
+
auth: PublicAuthSchema.default("token"),
|
|
41
|
+
user: BasicUserSchema.optional()
|
|
42
|
+
}).refine((input) => input.auth === "basic" || input.user === void 0, {
|
|
43
|
+
message: "only basic auth takes a user",
|
|
44
|
+
path: ["user"]
|
|
45
|
+
});
|
|
46
|
+
z.object({
|
|
47
|
+
url: z.url(),
|
|
48
|
+
auth: PublicAuthSchema,
|
|
49
|
+
user: z.string().nullable(),
|
|
50
|
+
credential: z.string().nullable(),
|
|
51
|
+
warning: z.string().optional()
|
|
52
|
+
});
|
|
53
|
+
z.string().regex(/^[\w.:-]{1,64}$/, "must be 1–64 letters, digits, dots, underscores, colons or hyphens");
|
|
54
|
+
z.int().min(10).max(3600);
|
|
55
|
+
const LeaseOwnerSchema = z.object({
|
|
56
|
+
principal: z.string(),
|
|
57
|
+
display: z.string(),
|
|
58
|
+
label: z.string()
|
|
59
|
+
});
|
|
60
|
+
const LeaseSchema = z.object({
|
|
61
|
+
name: NameSchema,
|
|
62
|
+
owner: LeaseOwnerSchema,
|
|
63
|
+
until: z.date().nullable()
|
|
64
|
+
});
|
|
65
|
+
const LeaseSummarySchema = z.object({
|
|
66
|
+
leases: z.array(LeaseSchema).readonly(),
|
|
67
|
+
otherCount: z.int().nonnegative()
|
|
68
|
+
});
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region ../api/src/move-schema.ts
|
|
71
|
+
const MoveStateSchema = z.enum([
|
|
72
|
+
"sending",
|
|
73
|
+
"moved",
|
|
74
|
+
"receiving"
|
|
75
|
+
]);
|
|
76
|
+
const PeerUrlSchema = z.url({ protocol: /^https?$/ });
|
|
77
|
+
z.object({
|
|
78
|
+
bytes: z.int().nonnegative(),
|
|
79
|
+
checkpoints: z.int().nonnegative()
|
|
80
|
+
});
|
|
81
|
+
z.object({
|
|
82
|
+
ticket: z.string(),
|
|
83
|
+
expiresAt: z.date(),
|
|
84
|
+
peerUrl: PeerUrlSchema
|
|
85
|
+
});
|
|
86
|
+
z.object({
|
|
87
|
+
state: MoveStateSchema.nullable(),
|
|
88
|
+
peer: z.string().nullable(),
|
|
89
|
+
sentBytes: z.int().nonnegative(),
|
|
90
|
+
totalBytes: z.int().nonnegative(),
|
|
91
|
+
isDone: z.boolean(),
|
|
92
|
+
error: z.string().nullable()
|
|
93
|
+
});
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region ../api/src/imp-schema.ts
|
|
96
|
+
const ImpStateSchema = z.enum([
|
|
97
|
+
"creating",
|
|
98
|
+
"running",
|
|
99
|
+
"sleeping",
|
|
100
|
+
"stopped",
|
|
101
|
+
"error"
|
|
102
|
+
]);
|
|
103
|
+
const OutdatedPartSchema = z.enum([
|
|
104
|
+
"firecracker",
|
|
105
|
+
"kernel",
|
|
106
|
+
"agent",
|
|
107
|
+
"impd",
|
|
108
|
+
"ipv6"
|
|
109
|
+
]);
|
|
110
|
+
const ImpResourcesSchema = z.object({
|
|
111
|
+
wakeCount: z.int().nonnegative(),
|
|
112
|
+
awakeMs: z.int().nonnegative(),
|
|
113
|
+
sample: z.object({
|
|
114
|
+
measuredAt: z.date(),
|
|
115
|
+
since: z.date(),
|
|
116
|
+
cpuPercent: z.number().nonnegative().optional(),
|
|
117
|
+
cpuThrottledMs: z.int().nonnegative(),
|
|
118
|
+
netRxBytes: z.int().nonnegative(),
|
|
119
|
+
netTxBytes: z.int().nonnegative()
|
|
120
|
+
}).optional()
|
|
121
|
+
});
|
|
122
|
+
z.object({
|
|
123
|
+
id: z.string(),
|
|
124
|
+
name: NameSchema,
|
|
125
|
+
image: NameSchema,
|
|
126
|
+
state: ImpStateSchema,
|
|
127
|
+
vcpus: z.int().positive(),
|
|
128
|
+
memoryMib: z.int().positive(),
|
|
129
|
+
diskMib: z.int().positive(),
|
|
130
|
+
diskUsage: z.object({
|
|
131
|
+
exclusiveBytes: z.int().nonnegative(),
|
|
132
|
+
sharedBytes: z.int().nonnegative(),
|
|
133
|
+
measuredAt: z.date(),
|
|
134
|
+
isPartial: z.boolean(),
|
|
135
|
+
isUpperBound: z.boolean()
|
|
136
|
+
}).optional(),
|
|
137
|
+
ip: z.ipv4(),
|
|
138
|
+
slot: z.int().nonnegative(),
|
|
139
|
+
port: z.int().positive(),
|
|
140
|
+
httpPort: z.int().positive(),
|
|
141
|
+
url: z.url(),
|
|
142
|
+
public: z.object({ auth: PublicAuthSchema }).optional(),
|
|
143
|
+
createdAt: z.date(),
|
|
144
|
+
lastActiveAt: z.date(),
|
|
145
|
+
ramMib: z.int().nonnegative().optional(),
|
|
146
|
+
rssMib: z.int().nonnegative().optional(),
|
|
147
|
+
sleptAt: z.date().optional(),
|
|
148
|
+
holdUntil: z.date().optional(),
|
|
149
|
+
leases: LeaseSummarySchema.optional(),
|
|
150
|
+
error: z.string().optional(),
|
|
151
|
+
sessions: z.int().nonnegative().optional(),
|
|
152
|
+
coldBootReason: z.string().optional(),
|
|
153
|
+
agentSilentSince: z.date().optional(),
|
|
154
|
+
outdated: z.array(OutdatedPartSchema).readonly().optional(),
|
|
155
|
+
cpu: z.object({
|
|
156
|
+
limit: z.number().positive().nullable(),
|
|
157
|
+
weight: z.int()
|
|
158
|
+
}).optional(),
|
|
159
|
+
resources: ImpResourcesSchema.optional(),
|
|
160
|
+
move: MoveStateSchema.optional()
|
|
161
|
+
});
|
|
31
162
|
//#endregion
|
|
32
163
|
//#region ../api/src/image-schema.ts
|
|
33
164
|
const ImageSourceSchema = z.enum(["oci", "imp"]);
|
|
@@ -54,6 +185,67 @@ const ImageBuildErrorSchema = z.object({
|
|
|
54
185
|
message: z.string()
|
|
55
186
|
});
|
|
56
187
|
//#endregion
|
|
188
|
+
//#region ../api/src/session-output-schema.ts
|
|
189
|
+
const ExecutionGenerationSchema = z.string().regex(/^[0-9a-f]{32}$/);
|
|
190
|
+
const OffsetSchema = z.int().nonnegative();
|
|
191
|
+
const ColdBootCauseSchema = z.enum([
|
|
192
|
+
"start",
|
|
193
|
+
"wake_fallback",
|
|
194
|
+
"watchdog",
|
|
195
|
+
"restore",
|
|
196
|
+
"recovery",
|
|
197
|
+
"unknown"
|
|
198
|
+
]);
|
|
199
|
+
const ColdBootSchema = z.object({
|
|
200
|
+
bootId: z.string(),
|
|
201
|
+
cause: ColdBootCauseSchema,
|
|
202
|
+
at: z.iso.datetime()
|
|
203
|
+
}).readonly();
|
|
204
|
+
const ColdBootsSchema = z.array(ColdBootSchema).max(4).readonly();
|
|
205
|
+
const PreviousGenerationSchema = z.object({
|
|
206
|
+
executionGeneration: ExecutionGenerationSchema,
|
|
207
|
+
end: OffsetSchema,
|
|
208
|
+
exitCode: z.int().nullable()
|
|
209
|
+
}).readonly();
|
|
210
|
+
const ResumeFromSchema = z.object({
|
|
211
|
+
executionGeneration: ExecutionGenerationSchema,
|
|
212
|
+
offset: OffsetSchema
|
|
213
|
+
}).readonly();
|
|
214
|
+
const ResumeResultSchema = z.discriminatedUnion("kind", [
|
|
215
|
+
z.object({ kind: z.literal("exact") }),
|
|
216
|
+
z.object({
|
|
217
|
+
kind: z.literal("gap"),
|
|
218
|
+
from: OffsetSchema,
|
|
219
|
+
to: OffsetSchema
|
|
220
|
+
}),
|
|
221
|
+
z.object({
|
|
222
|
+
kind: z.literal("generation_changed"),
|
|
223
|
+
executionGeneration: ExecutionGenerationSchema,
|
|
224
|
+
firstOffset: OffsetSchema
|
|
225
|
+
})
|
|
226
|
+
]).readonly();
|
|
227
|
+
const SessionOutputSchema = z.discriminatedUnion("continuity", [z.object({ continuity: z.literal("none") }), z.object({
|
|
228
|
+
continuity: z.literal("offsets"),
|
|
229
|
+
bootId: z.string(),
|
|
230
|
+
executionGeneration: ExecutionGenerationSchema,
|
|
231
|
+
bufferStart: OffsetSchema,
|
|
232
|
+
end: OffsetSchema,
|
|
233
|
+
offset: OffsetSchema,
|
|
234
|
+
prelude: OffsetSchema,
|
|
235
|
+
coldBoots: ColdBootsSchema,
|
|
236
|
+
previous: PreviousGenerationSchema.optional(),
|
|
237
|
+
resume: ResumeResultSchema.optional()
|
|
238
|
+
})]).readonly();
|
|
239
|
+
const NoSessionDataSchema = z.object({
|
|
240
|
+
bootId: z.string(),
|
|
241
|
+
coldBoots: ColdBootsSchema,
|
|
242
|
+
previous: PreviousGenerationSchema.optional()
|
|
243
|
+
}).readonly();
|
|
244
|
+
const InvalidResumeDataSchema = z.object({
|
|
245
|
+
end: OffsetSchema,
|
|
246
|
+
bufferStart: OffsetSchema
|
|
247
|
+
}).readonly();
|
|
248
|
+
//#endregion
|
|
57
249
|
//#region ../api/src/session-schema.ts
|
|
58
250
|
const SessionNameSchema = z.string().regex(/^[a-z0-9][a-z0-9-]{0,31}$/, "must be a lowercase letter or digit followed by up to 31 lowercase letters, digits or hyphens");
|
|
59
251
|
const SessionExitSchema = z.object({
|
|
@@ -69,7 +261,12 @@ z.object({
|
|
|
69
261
|
cols: z.int().positive(),
|
|
70
262
|
rows: z.int().positive(),
|
|
71
263
|
startedAt: z.date(),
|
|
72
|
-
exit: SessionExitSchema.optional()
|
|
264
|
+
exit: SessionExitSchema.optional(),
|
|
265
|
+
continuity: z.enum(["none", "offsets"]).optional(),
|
|
266
|
+
executionGeneration: ExecutionGenerationSchema.optional(),
|
|
267
|
+
bootId: z.string().optional(),
|
|
268
|
+
end: z.int().nonnegative().optional(),
|
|
269
|
+
endObservedAt: z.date().optional()
|
|
73
270
|
});
|
|
74
271
|
//#endregion
|
|
75
272
|
//#region ../api/src/exec-protocol.ts
|
|
@@ -92,10 +289,14 @@ const ExecStartMessageSchema = z.object({
|
|
|
92
289
|
rows: DimensionSchema.optional(),
|
|
93
290
|
session: SessionNameSchema.optional(),
|
|
94
291
|
tool: z.enum(["tar"]).optional(),
|
|
95
|
-
killGraceMs: z.int().min(1).max(6e4).optional()
|
|
292
|
+
killGraceMs: z.int().min(1).max(6e4).optional(),
|
|
293
|
+
resumeFrom: ResumeFromSchema.optional()
|
|
96
294
|
}).refine((start) => start.session === void 0 || start.tty, {
|
|
97
295
|
message: "a session needs a tty",
|
|
98
296
|
path: ["tty"]
|
|
297
|
+
}).refine((start) => start.resumeFrom === void 0 || start.session !== void 0, {
|
|
298
|
+
message: "only a session resumes",
|
|
299
|
+
path: ["resumeFrom"]
|
|
99
300
|
}).refine((start) => start.killGraceMs === void 0 || !start.tty, {
|
|
100
301
|
message: "a tty exec takes no kill grace",
|
|
101
302
|
path: ["killGraceMs"]
|
|
@@ -108,7 +309,9 @@ const ExecAttachMessageSchema = z.object({
|
|
|
108
309
|
name: NameSchema,
|
|
109
310
|
session: SessionNameSchema,
|
|
110
311
|
cols: DimensionSchema.optional(),
|
|
111
|
-
rows: DimensionSchema.optional()
|
|
312
|
+
rows: DimensionSchema.optional(),
|
|
313
|
+
resumeFrom: ResumeFromSchema.optional(),
|
|
314
|
+
wake: z.boolean().optional()
|
|
112
315
|
});
|
|
113
316
|
z.discriminatedUnion("type", [
|
|
114
317
|
ExecStartMessageSchema,
|
|
@@ -134,12 +337,14 @@ const ExecServerMessageSchema = z.discriminatedUnion("type", [
|
|
|
134
337
|
pid: z.int().positive(),
|
|
135
338
|
session: SessionNameSchema.optional(),
|
|
136
339
|
created: z.boolean().optional(),
|
|
137
|
-
groupKill: z.boolean().optional()
|
|
340
|
+
groupKill: z.boolean().optional(),
|
|
341
|
+
output: SessionOutputSchema.optional()
|
|
138
342
|
}),
|
|
139
343
|
z.object({
|
|
140
344
|
type: z.literal("exit"),
|
|
141
345
|
code: z.int().nullable(),
|
|
142
|
-
signal: z.string().nullable()
|
|
346
|
+
signal: z.string().nullable(),
|
|
347
|
+
offset: z.int().nonnegative().optional()
|
|
143
348
|
}),
|
|
144
349
|
z.object({
|
|
145
350
|
type: z.literal("detached"),
|
|
@@ -147,7 +352,8 @@ const ExecServerMessageSchema = z.discriminatedUnion("type", [
|
|
|
147
352
|
"taken_over",
|
|
148
353
|
"slow",
|
|
149
354
|
"lost"
|
|
150
|
-
])
|
|
355
|
+
]),
|
|
356
|
+
offset: z.int().nonnegative().optional()
|
|
151
357
|
}),
|
|
152
358
|
z.object({
|
|
153
359
|
type: z.literal("stdin_ack"),
|
|
@@ -235,6 +441,102 @@ const TunnelServerMessageSchema = z.discriminatedUnion("type", [
|
|
|
235
441
|
})
|
|
236
442
|
]);
|
|
237
443
|
//#endregion
|
|
444
|
+
//#region ../api/src/define-errors.ts
|
|
445
|
+
function defineErrors(errors) {
|
|
446
|
+
return errors;
|
|
447
|
+
}
|
|
448
|
+
//#endregion
|
|
449
|
+
//#region ../api/src/imp-errors.ts
|
|
450
|
+
const ResourceKindSchema = z.enum([
|
|
451
|
+
"imp",
|
|
452
|
+
"image",
|
|
453
|
+
"checkpoint",
|
|
454
|
+
"session",
|
|
455
|
+
"service",
|
|
456
|
+
"secret",
|
|
457
|
+
"grant",
|
|
458
|
+
"backup",
|
|
459
|
+
"token",
|
|
460
|
+
"ssh-key",
|
|
461
|
+
"network"
|
|
462
|
+
]);
|
|
463
|
+
const ResourceDataSchema = z.object({
|
|
464
|
+
kind: ResourceKindSchema,
|
|
465
|
+
name: z.string()
|
|
466
|
+
});
|
|
467
|
+
const ProtectedImpSchema = z.object({
|
|
468
|
+
name: NameSchema,
|
|
469
|
+
ramMib: z.int().nonnegative(),
|
|
470
|
+
leased: z.boolean(),
|
|
471
|
+
busy: z.boolean()
|
|
472
|
+
});
|
|
473
|
+
const IMP_ERRORS = defineErrors({
|
|
474
|
+
NOT_FOUND: {
|
|
475
|
+
message: "Not found",
|
|
476
|
+
data: ResourceDataSchema
|
|
477
|
+
},
|
|
478
|
+
CONFLICT: {
|
|
479
|
+
message: "Already exists",
|
|
480
|
+
data: ResourceDataSchema
|
|
481
|
+
},
|
|
482
|
+
FORBIDDEN: { message: "Not allowed" },
|
|
483
|
+
PRECONDITION_FAILED: { message: "Not possible on this host" },
|
|
484
|
+
RAM_BUDGET_EXCEEDED: {
|
|
485
|
+
message: "Not enough RAM budget, even after sleeping idle imps",
|
|
486
|
+
status: 503,
|
|
487
|
+
data: z.object({
|
|
488
|
+
budgetMib: z.int().nonnegative(),
|
|
489
|
+
usedMib: z.int().nonnegative(),
|
|
490
|
+
requestedMib: z.int().nonnegative(),
|
|
491
|
+
neededMib: z.int().nonnegative().optional(),
|
|
492
|
+
protected: z.array(ProtectedImpSchema).readonly().optional(),
|
|
493
|
+
protectedHidden: z.int().nonnegative().optional()
|
|
494
|
+
})
|
|
495
|
+
},
|
|
496
|
+
SERVICE_UNAVAILABLE: { message: "impd is stopping" },
|
|
497
|
+
INVALID_STATE: {
|
|
498
|
+
message: "The imp is not in a state that allows this",
|
|
499
|
+
status: 409,
|
|
500
|
+
data: z.object({
|
|
501
|
+
state: ImpStateSchema,
|
|
502
|
+
allowed: z.array(ImpStateSchema),
|
|
503
|
+
coldBoots: ColdBootsSchema.optional()
|
|
504
|
+
})
|
|
505
|
+
},
|
|
506
|
+
INVALID_RESUME: {
|
|
507
|
+
message: "The resume offset is past the end of the output",
|
|
508
|
+
status: 409,
|
|
509
|
+
data: InvalidResumeDataSchema
|
|
510
|
+
},
|
|
511
|
+
DISK_FULL: {
|
|
512
|
+
message: "Not enough free disk on the host",
|
|
513
|
+
status: 507,
|
|
514
|
+
data: z.object({
|
|
515
|
+
availableBytes: z.int().nonnegative(),
|
|
516
|
+
reserveBytes: z.int().nonnegative(),
|
|
517
|
+
requestedBytes: z.int().nonnegative()
|
|
518
|
+
})
|
|
519
|
+
},
|
|
520
|
+
LEASED: {
|
|
521
|
+
message: "The imp is leased",
|
|
522
|
+
status: 409,
|
|
523
|
+
data: LeaseSummarySchema
|
|
524
|
+
},
|
|
525
|
+
LEASE_NOT_HELD: {
|
|
526
|
+
message: "The caller holds no such lease",
|
|
527
|
+
status: 409
|
|
528
|
+
},
|
|
529
|
+
AGENT_OUTDATED: {
|
|
530
|
+
message: "The imp's agent is too old for this",
|
|
531
|
+
status: 409
|
|
532
|
+
},
|
|
533
|
+
MOVING: {
|
|
534
|
+
message: "The imp is moving between hosts",
|
|
535
|
+
status: 409,
|
|
536
|
+
data: z.object({ retryAfterS: z.int().positive() })
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
//#endregion
|
|
238
540
|
//#region ../api/src/login-shell.ts
|
|
239
541
|
const CONSOLE_SHELL = [
|
|
240
542
|
"uid=$(id -u 2>/dev/null) || uid=0",
|
|
@@ -297,15 +599,6 @@ var ExecError = class extends Error {
|
|
|
297
599
|
this.data = options.data;
|
|
298
600
|
}
|
|
299
601
|
};
|
|
300
|
-
function toExecError(outcome) {
|
|
301
|
-
if (outcome.kind === "failed") return new ExecError(outcome.code ?? "EXEC_ERROR", outcome.message, { data: outcome.data });
|
|
302
|
-
if (outcome.kind === "unauthorized") return new ExecError("UNAUTHORIZED", outcome.ticketRefused === true ? "impd refused the exec ticket: it expired (30 s) or was used already" : "impd rejected the token");
|
|
303
|
-
if (outcome.kind === "unreachable") return new ExecError("UNREACHABLE", `cannot reach impd (${outcome.detail})`);
|
|
304
|
-
if (outcome.kind === "detached") return new ExecError("DETACHED", `detached from the session (${outcome.reason})`, { data: { reason: outcome.reason } });
|
|
305
|
-
if (outcome.kind === "closed") return outcome.closeCode === 1012 ? new ExecError("RESTARTING", "impd is restarting") : new ExecError("CONNECTION_CLOSED", `exec connection closed (${outcome.reason})`);
|
|
306
|
-
if (outcome.kind === "bad_message") return new ExecError("BAD_MESSAGE", `bad message from impd: ${outcome.detail}`);
|
|
307
|
-
return new ExecError("LOCAL_ERROR", "an output handler threw", { cause: outcome.error });
|
|
308
|
-
}
|
|
309
602
|
//#endregion
|
|
310
603
|
//#region src/exec/check-impd-access.ts
|
|
311
604
|
const CHECK_TIMEOUT_MS = 5e3;
|
|
@@ -391,16 +684,19 @@ function openExecSession(options) {
|
|
|
391
684
|
pid: message.pid,
|
|
392
685
|
session: message.session ?? null,
|
|
393
686
|
created: message.created ?? false,
|
|
394
|
-
groupKill: message.groupKill ?? false
|
|
687
|
+
groupKill: message.groupKill ?? false,
|
|
688
|
+
output: message.output ?? { continuity: "none" }
|
|
395
689
|
});
|
|
396
690
|
} else if (message.type === "exit") resolveOutcome({
|
|
397
691
|
kind: "exit",
|
|
398
692
|
code: message.code,
|
|
399
|
-
signal: message.signal
|
|
693
|
+
signal: message.signal,
|
|
694
|
+
...message.offset !== void 0 && { offset: message.offset }
|
|
400
695
|
});
|
|
401
696
|
else if (message.type === "detached") resolveOutcome({
|
|
402
697
|
kind: "detached",
|
|
403
|
-
reason: message.reason
|
|
698
|
+
reason: message.reason,
|
|
699
|
+
...message.offset !== void 0 && { offset: message.offset }
|
|
404
700
|
});
|
|
405
701
|
else if (message.type === "stdin_ack") {} else resolveOutcome({
|
|
406
702
|
kind: "failed",
|
|
@@ -510,6 +806,59 @@ function buildOpenMessage(start) {
|
|
|
510
806
|
};
|
|
511
807
|
}
|
|
512
808
|
//#endregion
|
|
809
|
+
//#region src/exec/invalid-resume-error.ts
|
|
810
|
+
var InvalidResumeError = class extends ExecError {
|
|
811
|
+
constructor(message, data) {
|
|
812
|
+
super("INVALID_RESUME", message, { data });
|
|
813
|
+
this.name = "InvalidResumeError";
|
|
814
|
+
}
|
|
815
|
+
};
|
|
816
|
+
//#endregion
|
|
817
|
+
//#region src/exec/invalid-state-error.ts
|
|
818
|
+
var InvalidStateError = class extends ExecError {
|
|
819
|
+
constructor(message, data) {
|
|
820
|
+
super("INVALID_STATE", message, { data });
|
|
821
|
+
this.name = "InvalidStateError";
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
//#endregion
|
|
825
|
+
//#region src/exec/no-session-error.ts
|
|
826
|
+
var NoSessionError = class extends ExecError {
|
|
827
|
+
constructor(message, data) {
|
|
828
|
+
super("NO_SESSION", message, { data });
|
|
829
|
+
this.name = "NoSessionError";
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
//#endregion
|
|
833
|
+
//#region src/exec/to-exec-error.ts
|
|
834
|
+
function toExecError(outcome) {
|
|
835
|
+
if (outcome.kind === "failed") return toFailedError(outcome.code, outcome.message, outcome.data);
|
|
836
|
+
if (outcome.kind === "unauthorized") return new ExecError("UNAUTHORIZED", outcome.ticketRefused === true ? "impd refused the exec ticket: it expired (30 s) or was used already" : "impd rejected the token");
|
|
837
|
+
if (outcome.kind === "unreachable") return new ExecError("UNREACHABLE", `cannot reach impd (${outcome.detail})`);
|
|
838
|
+
if (outcome.kind === "detached") return new ExecError("DETACHED", `detached from the session (${outcome.reason})`, { data: {
|
|
839
|
+
reason: outcome.reason,
|
|
840
|
+
...outcome.offset !== void 0 && { offset: outcome.offset }
|
|
841
|
+
} });
|
|
842
|
+
if (outcome.kind === "closed") return outcome.closeCode === 1012 ? new ExecError("RESTARTING", "impd is restarting") : new ExecError("CONNECTION_CLOSED", `exec connection closed (${outcome.reason})`);
|
|
843
|
+
if (outcome.kind === "bad_message") return new ExecError("BAD_MESSAGE", `bad message from impd: ${outcome.detail}`);
|
|
844
|
+
return new ExecError("LOCAL_ERROR", "an output handler threw", { cause: outcome.error });
|
|
845
|
+
}
|
|
846
|
+
function toFailedError(code, message, data) {
|
|
847
|
+
if (code === "NO_SESSION") {
|
|
848
|
+
const parsed = NoSessionDataSchema.safeParse(data);
|
|
849
|
+
return new NoSessionError(message, parsed.success ? parsed.data : void 0);
|
|
850
|
+
}
|
|
851
|
+
if (code === "INVALID_STATE") {
|
|
852
|
+
const parsed = IMP_ERRORS.INVALID_STATE.data.safeParse(data);
|
|
853
|
+
if (parsed.success) return new InvalidStateError(message, parsed.data);
|
|
854
|
+
}
|
|
855
|
+
if (code === "INVALID_RESUME") {
|
|
856
|
+
const parsed = InvalidResumeDataSchema.safeParse(data);
|
|
857
|
+
if (parsed.success) return new InvalidResumeError(message, parsed.data);
|
|
858
|
+
}
|
|
859
|
+
return new ExecError(code ?? "EXEC_ERROR", message, { data });
|
|
860
|
+
}
|
|
861
|
+
//#endregion
|
|
513
862
|
//#region src/exec/open-exec.ts
|
|
514
863
|
const DEFAULT_MAX_UNREAD_BYTES = 8388608;
|
|
515
864
|
const TTY_SIGNAL_KEYS = {
|
|
@@ -527,7 +876,8 @@ function openExec(deps, name, argv, options = {}) {
|
|
|
527
876
|
...options.cols !== void 0 && { cols: options.cols },
|
|
528
877
|
...options.rows !== void 0 && { rows: options.rows },
|
|
529
878
|
...options.session !== void 0 && { session: options.session },
|
|
530
|
-
...options.killGraceMs !== void 0 && { killGraceMs: options.killGraceMs }
|
|
879
|
+
...options.killGraceMs !== void 0 && { killGraceMs: options.killGraceMs },
|
|
880
|
+
...options.resumeFrom !== void 0 && { resumeFrom: options.resumeFrom }
|
|
531
881
|
});
|
|
532
882
|
}
|
|
533
883
|
function openAttach(deps, name, session, options = {}) {
|
|
@@ -535,7 +885,9 @@ function openAttach(deps, name, session, options = {}) {
|
|
|
535
885
|
name,
|
|
536
886
|
session,
|
|
537
887
|
...options.cols !== void 0 && { cols: options.cols },
|
|
538
|
-
...options.rows !== void 0 && { rows: options.rows }
|
|
888
|
+
...options.rows !== void 0 && { rows: options.rows },
|
|
889
|
+
...options.resumeFrom !== void 0 && { resumeFrom: options.resumeFrom },
|
|
890
|
+
...options.wake !== void 0 && { wake: options.wake }
|
|
539
891
|
});
|
|
540
892
|
}
|
|
541
893
|
async function openHandle(deps, options, tty, start) {
|
|
@@ -606,7 +958,8 @@ async function openHandle(deps, options, tty, start) {
|
|
|
606
958
|
const outcome = await session.outcome;
|
|
607
959
|
const result = outcome.kind === "exit" ? { value: {
|
|
608
960
|
code: outcome.code,
|
|
609
|
-
signal: outcome.signal
|
|
961
|
+
signal: outcome.signal,
|
|
962
|
+
...outcome.offset !== void 0 && { offset: outcome.offset }
|
|
610
963
|
} } : { error: toExecError(outcome) };
|
|
611
964
|
resolveHandle(result);
|
|
612
965
|
};
|
|
@@ -1046,4 +1399,4 @@ function openReverseForward(options) {
|
|
|
1046
1399
|
};
|
|
1047
1400
|
}
|
|
1048
1401
|
//#endregion
|
|
1049
|
-
export { CLIENT_VERSION, CONSOLE_SHELL, ExecError, ORPCError, createImpClient, isDefinedError, openExecSession, openReverseForward, safe };
|
|
1402
|
+
export { CLIENT_VERSION, CONSOLE_SHELL, ExecError, InvalidResumeError, InvalidStateError, NoSessionError, ORPCError, createImpClient, isDefinedError, openExecSession, openReverseForward, safe };
|