@zgeoff/imp-client 0.16.0 → 0.18.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 +1687 -73
- package/dist/index.js +380 -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.18.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,23 +289,33 @@ const ExecStartMessageSchema = z.object({
|
|
|
92
289
|
rows: DimensionSchema.optional(),
|
|
93
290
|
session: SessionNameSchema.optional(),
|
|
94
291
|
tool: z.enum(["tar"]).optional(),
|
|
95
|
-
|
|
292
|
+
outer: z.boolean().optional(),
|
|
293
|
+
killGraceMs: z.int().min(1).max(6e4).optional(),
|
|
294
|
+
resumeFrom: ResumeFromSchema.optional()
|
|
96
295
|
}).refine((start) => start.session === void 0 || start.tty, {
|
|
97
296
|
message: "a session needs a tty",
|
|
98
297
|
path: ["tty"]
|
|
298
|
+
}).refine((start) => start.resumeFrom === void 0 || start.session !== void 0, {
|
|
299
|
+
message: "only a session resumes",
|
|
300
|
+
path: ["resumeFrom"]
|
|
99
301
|
}).refine((start) => start.killGraceMs === void 0 || !start.tty, {
|
|
100
302
|
message: "a tty exec takes no kill grace",
|
|
101
303
|
path: ["killGraceMs"]
|
|
102
304
|
}).refine((start) => start.tool === void 0 || !start.tty && start.session === void 0 && start.env === void 0 && start.cwd === void 0, {
|
|
103
305
|
message: "a tool takes no tty, session, env or cwd",
|
|
104
306
|
path: ["tool"]
|
|
307
|
+
}).refine((start) => start.outer !== true || start.tool === void 0 && start.session === void 0, {
|
|
308
|
+
message: "an outer exec takes no tool or session",
|
|
309
|
+
path: ["outer"]
|
|
105
310
|
});
|
|
106
311
|
const ExecAttachMessageSchema = z.object({
|
|
107
312
|
type: z.literal("attach"),
|
|
108
313
|
name: NameSchema,
|
|
109
314
|
session: SessionNameSchema,
|
|
110
315
|
cols: DimensionSchema.optional(),
|
|
111
|
-
rows: DimensionSchema.optional()
|
|
316
|
+
rows: DimensionSchema.optional(),
|
|
317
|
+
resumeFrom: ResumeFromSchema.optional(),
|
|
318
|
+
wake: z.boolean().optional()
|
|
112
319
|
});
|
|
113
320
|
z.discriminatedUnion("type", [
|
|
114
321
|
ExecStartMessageSchema,
|
|
@@ -134,12 +341,14 @@ const ExecServerMessageSchema = z.discriminatedUnion("type", [
|
|
|
134
341
|
pid: z.int().positive(),
|
|
135
342
|
session: SessionNameSchema.optional(),
|
|
136
343
|
created: z.boolean().optional(),
|
|
137
|
-
groupKill: z.boolean().optional()
|
|
344
|
+
groupKill: z.boolean().optional(),
|
|
345
|
+
output: SessionOutputSchema.optional()
|
|
138
346
|
}),
|
|
139
347
|
z.object({
|
|
140
348
|
type: z.literal("exit"),
|
|
141
349
|
code: z.int().nullable(),
|
|
142
|
-
signal: z.string().nullable()
|
|
350
|
+
signal: z.string().nullable(),
|
|
351
|
+
offset: z.int().nonnegative().optional()
|
|
143
352
|
}),
|
|
144
353
|
z.object({
|
|
145
354
|
type: z.literal("detached"),
|
|
@@ -147,7 +356,8 @@ const ExecServerMessageSchema = z.discriminatedUnion("type", [
|
|
|
147
356
|
"taken_over",
|
|
148
357
|
"slow",
|
|
149
358
|
"lost"
|
|
150
|
-
])
|
|
359
|
+
]),
|
|
360
|
+
offset: z.int().nonnegative().optional()
|
|
151
361
|
}),
|
|
152
362
|
z.object({
|
|
153
363
|
type: z.literal("stdin_ack"),
|
|
@@ -235,6 +445,102 @@ const TunnelServerMessageSchema = z.discriminatedUnion("type", [
|
|
|
235
445
|
})
|
|
236
446
|
]);
|
|
237
447
|
//#endregion
|
|
448
|
+
//#region ../api/src/define-errors.ts
|
|
449
|
+
function defineErrors(errors) {
|
|
450
|
+
return errors;
|
|
451
|
+
}
|
|
452
|
+
//#endregion
|
|
453
|
+
//#region ../api/src/imp-errors.ts
|
|
454
|
+
const ResourceKindSchema = z.enum([
|
|
455
|
+
"imp",
|
|
456
|
+
"image",
|
|
457
|
+
"checkpoint",
|
|
458
|
+
"session",
|
|
459
|
+
"service",
|
|
460
|
+
"secret",
|
|
461
|
+
"grant",
|
|
462
|
+
"backup",
|
|
463
|
+
"token",
|
|
464
|
+
"ssh-key",
|
|
465
|
+
"network"
|
|
466
|
+
]);
|
|
467
|
+
const ResourceDataSchema = z.object({
|
|
468
|
+
kind: ResourceKindSchema,
|
|
469
|
+
name: z.string()
|
|
470
|
+
});
|
|
471
|
+
const ProtectedImpSchema = z.object({
|
|
472
|
+
name: NameSchema,
|
|
473
|
+
ramMib: z.int().nonnegative(),
|
|
474
|
+
leased: z.boolean(),
|
|
475
|
+
busy: z.boolean()
|
|
476
|
+
});
|
|
477
|
+
const IMP_ERRORS = defineErrors({
|
|
478
|
+
NOT_FOUND: {
|
|
479
|
+
message: "Not found",
|
|
480
|
+
data: ResourceDataSchema
|
|
481
|
+
},
|
|
482
|
+
CONFLICT: {
|
|
483
|
+
message: "Already exists",
|
|
484
|
+
data: ResourceDataSchema
|
|
485
|
+
},
|
|
486
|
+
FORBIDDEN: { message: "Not allowed" },
|
|
487
|
+
PRECONDITION_FAILED: { message: "Not possible on this host" },
|
|
488
|
+
RAM_BUDGET_EXCEEDED: {
|
|
489
|
+
message: "Not enough RAM budget, even after sleeping idle imps",
|
|
490
|
+
status: 503,
|
|
491
|
+
data: z.object({
|
|
492
|
+
budgetMib: z.int().nonnegative(),
|
|
493
|
+
usedMib: z.int().nonnegative(),
|
|
494
|
+
requestedMib: z.int().nonnegative(),
|
|
495
|
+
neededMib: z.int().nonnegative().optional(),
|
|
496
|
+
protected: z.array(ProtectedImpSchema).readonly().optional(),
|
|
497
|
+
protectedHidden: z.int().nonnegative().optional()
|
|
498
|
+
})
|
|
499
|
+
},
|
|
500
|
+
SERVICE_UNAVAILABLE: { message: "impd is stopping" },
|
|
501
|
+
INVALID_STATE: {
|
|
502
|
+
message: "The imp is not in a state that allows this",
|
|
503
|
+
status: 409,
|
|
504
|
+
data: z.object({
|
|
505
|
+
state: ImpStateSchema,
|
|
506
|
+
allowed: z.array(ImpStateSchema),
|
|
507
|
+
coldBoots: ColdBootsSchema.optional()
|
|
508
|
+
})
|
|
509
|
+
},
|
|
510
|
+
INVALID_RESUME: {
|
|
511
|
+
message: "The resume offset is past the end of the output",
|
|
512
|
+
status: 409,
|
|
513
|
+
data: InvalidResumeDataSchema
|
|
514
|
+
},
|
|
515
|
+
DISK_FULL: {
|
|
516
|
+
message: "Not enough free disk on the host",
|
|
517
|
+
status: 507,
|
|
518
|
+
data: z.object({
|
|
519
|
+
availableBytes: z.int().nonnegative(),
|
|
520
|
+
reserveBytes: z.int().nonnegative(),
|
|
521
|
+
requestedBytes: z.int().nonnegative()
|
|
522
|
+
})
|
|
523
|
+
},
|
|
524
|
+
LEASED: {
|
|
525
|
+
message: "The imp is leased",
|
|
526
|
+
status: 409,
|
|
527
|
+
data: LeaseSummarySchema
|
|
528
|
+
},
|
|
529
|
+
LEASE_NOT_HELD: {
|
|
530
|
+
message: "The caller holds no such lease",
|
|
531
|
+
status: 409
|
|
532
|
+
},
|
|
533
|
+
AGENT_OUTDATED: {
|
|
534
|
+
message: "The imp's agent is too old for this",
|
|
535
|
+
status: 409
|
|
536
|
+
},
|
|
537
|
+
MOVING: {
|
|
538
|
+
message: "The imp is moving between hosts",
|
|
539
|
+
status: 409,
|
|
540
|
+
data: z.object({ retryAfterS: z.int().positive() })
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
//#endregion
|
|
238
544
|
//#region ../api/src/login-shell.ts
|
|
239
545
|
const CONSOLE_SHELL = [
|
|
240
546
|
"uid=$(id -u 2>/dev/null) || uid=0",
|
|
@@ -297,15 +603,6 @@ var ExecError = class extends Error {
|
|
|
297
603
|
this.data = options.data;
|
|
298
604
|
}
|
|
299
605
|
};
|
|
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
606
|
//#endregion
|
|
310
607
|
//#region src/exec/check-impd-access.ts
|
|
311
608
|
const CHECK_TIMEOUT_MS = 5e3;
|
|
@@ -391,16 +688,19 @@ function openExecSession(options) {
|
|
|
391
688
|
pid: message.pid,
|
|
392
689
|
session: message.session ?? null,
|
|
393
690
|
created: message.created ?? false,
|
|
394
|
-
groupKill: message.groupKill ?? false
|
|
691
|
+
groupKill: message.groupKill ?? false,
|
|
692
|
+
output: message.output ?? { continuity: "none" }
|
|
395
693
|
});
|
|
396
694
|
} else if (message.type === "exit") resolveOutcome({
|
|
397
695
|
kind: "exit",
|
|
398
696
|
code: message.code,
|
|
399
|
-
signal: message.signal
|
|
697
|
+
signal: message.signal,
|
|
698
|
+
...message.offset !== void 0 && { offset: message.offset }
|
|
400
699
|
});
|
|
401
700
|
else if (message.type === "detached") resolveOutcome({
|
|
402
701
|
kind: "detached",
|
|
403
|
-
reason: message.reason
|
|
702
|
+
reason: message.reason,
|
|
703
|
+
...message.offset !== void 0 && { offset: message.offset }
|
|
404
704
|
});
|
|
405
705
|
else if (message.type === "stdin_ack") {} else resolveOutcome({
|
|
406
706
|
kind: "failed",
|
|
@@ -510,6 +810,59 @@ function buildOpenMessage(start) {
|
|
|
510
810
|
};
|
|
511
811
|
}
|
|
512
812
|
//#endregion
|
|
813
|
+
//#region src/exec/invalid-resume-error.ts
|
|
814
|
+
var InvalidResumeError = class extends ExecError {
|
|
815
|
+
constructor(message, data) {
|
|
816
|
+
super("INVALID_RESUME", message, { data });
|
|
817
|
+
this.name = "InvalidResumeError";
|
|
818
|
+
}
|
|
819
|
+
};
|
|
820
|
+
//#endregion
|
|
821
|
+
//#region src/exec/invalid-state-error.ts
|
|
822
|
+
var InvalidStateError = class extends ExecError {
|
|
823
|
+
constructor(message, data) {
|
|
824
|
+
super("INVALID_STATE", message, { data });
|
|
825
|
+
this.name = "InvalidStateError";
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
//#endregion
|
|
829
|
+
//#region src/exec/no-session-error.ts
|
|
830
|
+
var NoSessionError = class extends ExecError {
|
|
831
|
+
constructor(message, data) {
|
|
832
|
+
super("NO_SESSION", message, { data });
|
|
833
|
+
this.name = "NoSessionError";
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
//#endregion
|
|
837
|
+
//#region src/exec/to-exec-error.ts
|
|
838
|
+
function toExecError(outcome) {
|
|
839
|
+
if (outcome.kind === "failed") return toFailedError(outcome.code, outcome.message, outcome.data);
|
|
840
|
+
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");
|
|
841
|
+
if (outcome.kind === "unreachable") return new ExecError("UNREACHABLE", `cannot reach impd (${outcome.detail})`);
|
|
842
|
+
if (outcome.kind === "detached") return new ExecError("DETACHED", `detached from the session (${outcome.reason})`, { data: {
|
|
843
|
+
reason: outcome.reason,
|
|
844
|
+
...outcome.offset !== void 0 && { offset: outcome.offset }
|
|
845
|
+
} });
|
|
846
|
+
if (outcome.kind === "closed") return outcome.closeCode === 1012 ? new ExecError("RESTARTING", "impd is restarting") : new ExecError("CONNECTION_CLOSED", `exec connection closed (${outcome.reason})`);
|
|
847
|
+
if (outcome.kind === "bad_message") return new ExecError("BAD_MESSAGE", `bad message from impd: ${outcome.detail}`);
|
|
848
|
+
return new ExecError("LOCAL_ERROR", "an output handler threw", { cause: outcome.error });
|
|
849
|
+
}
|
|
850
|
+
function toFailedError(code, message, data) {
|
|
851
|
+
if (code === "NO_SESSION") {
|
|
852
|
+
const parsed = NoSessionDataSchema.safeParse(data);
|
|
853
|
+
return new NoSessionError(message, parsed.success ? parsed.data : void 0);
|
|
854
|
+
}
|
|
855
|
+
if (code === "INVALID_STATE") {
|
|
856
|
+
const parsed = IMP_ERRORS.INVALID_STATE.data.safeParse(data);
|
|
857
|
+
if (parsed.success) return new InvalidStateError(message, parsed.data);
|
|
858
|
+
}
|
|
859
|
+
if (code === "INVALID_RESUME") {
|
|
860
|
+
const parsed = InvalidResumeDataSchema.safeParse(data);
|
|
861
|
+
if (parsed.success) return new InvalidResumeError(message, parsed.data);
|
|
862
|
+
}
|
|
863
|
+
return new ExecError(code ?? "EXEC_ERROR", message, { data });
|
|
864
|
+
}
|
|
865
|
+
//#endregion
|
|
513
866
|
//#region src/exec/open-exec.ts
|
|
514
867
|
const DEFAULT_MAX_UNREAD_BYTES = 8388608;
|
|
515
868
|
const TTY_SIGNAL_KEYS = {
|
|
@@ -527,7 +880,8 @@ function openExec(deps, name, argv, options = {}) {
|
|
|
527
880
|
...options.cols !== void 0 && { cols: options.cols },
|
|
528
881
|
...options.rows !== void 0 && { rows: options.rows },
|
|
529
882
|
...options.session !== void 0 && { session: options.session },
|
|
530
|
-
...options.killGraceMs !== void 0 && { killGraceMs: options.killGraceMs }
|
|
883
|
+
...options.killGraceMs !== void 0 && { killGraceMs: options.killGraceMs },
|
|
884
|
+
...options.resumeFrom !== void 0 && { resumeFrom: options.resumeFrom }
|
|
531
885
|
});
|
|
532
886
|
}
|
|
533
887
|
function openAttach(deps, name, session, options = {}) {
|
|
@@ -535,7 +889,9 @@ function openAttach(deps, name, session, options = {}) {
|
|
|
535
889
|
name,
|
|
536
890
|
session,
|
|
537
891
|
...options.cols !== void 0 && { cols: options.cols },
|
|
538
|
-
...options.rows !== void 0 && { rows: options.rows }
|
|
892
|
+
...options.rows !== void 0 && { rows: options.rows },
|
|
893
|
+
...options.resumeFrom !== void 0 && { resumeFrom: options.resumeFrom },
|
|
894
|
+
...options.wake !== void 0 && { wake: options.wake }
|
|
539
895
|
});
|
|
540
896
|
}
|
|
541
897
|
async function openHandle(deps, options, tty, start) {
|
|
@@ -606,7 +962,8 @@ async function openHandle(deps, options, tty, start) {
|
|
|
606
962
|
const outcome = await session.outcome;
|
|
607
963
|
const result = outcome.kind === "exit" ? { value: {
|
|
608
964
|
code: outcome.code,
|
|
609
|
-
signal: outcome.signal
|
|
965
|
+
signal: outcome.signal,
|
|
966
|
+
...outcome.offset !== void 0 && { offset: outcome.offset }
|
|
610
967
|
} } : { error: toExecError(outcome) };
|
|
611
968
|
resolveHandle(result);
|
|
612
969
|
};
|
|
@@ -1046,4 +1403,4 @@ function openReverseForward(options) {
|
|
|
1046
1403
|
};
|
|
1047
1404
|
}
|
|
1048
1405
|
//#endregion
|
|
1049
|
-
export { CLIENT_VERSION, CONSOLE_SHELL, ExecError, ORPCError, createImpClient, isDefinedError, openExecSession, openReverseForward, safe };
|
|
1406
|
+
export { CLIENT_VERSION, CONSOLE_SHELL, ExecError, InvalidResumeError, InvalidStateError, NoSessionError, ORPCError, createImpClient, isDefinedError, openExecSession, openReverseForward, safe };
|