@swipt/cli 0.1.0-nightly.43 → 0.1.0-nightly.45
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/client.mjs +103 -30
- package/connection.mjs +86 -26
- package/coredevice.mjs +68 -0
- package/device.mjs +274 -90
- package/ignore.mjs +17 -5
- package/metro.mjs +235 -65
- package/output.mjs +32 -7
- package/package.json +8 -3
- package/project.mjs +394 -106
- package/proto/system_pb.js +1 -1
- package/sideload/trust.js +235 -0
- package/sideload.mjs +649 -0
- package/swipt.mjs +374 -52
package/device.mjs
CHANGED
|
@@ -11,7 +11,14 @@ import { ValueSchema, timestampFromMs } from "@bufbuild/protobuf/wkt";
|
|
|
11
11
|
import { UsageError, unauthenticated } from "./client.mjs";
|
|
12
12
|
import { attach } from "./connection.mjs";
|
|
13
13
|
import { Ignorer, relativePath } from "./ignore.mjs";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
columns,
|
|
16
|
+
dateTime,
|
|
17
|
+
enumText,
|
|
18
|
+
printLog,
|
|
19
|
+
printScriptError,
|
|
20
|
+
serviceText,
|
|
21
|
+
} from "./output.mjs";
|
|
15
22
|
import { buildProject, loadProject } from "./project.mjs";
|
|
16
23
|
import { LogLevel } from "./proto/common_pb.js";
|
|
17
24
|
import { ServiceStatus, ServiceStatusSchema } from "./proto/swiplets_pb.js";
|
|
@@ -24,7 +31,8 @@ const { version } = createRequire(import.meta.url)("./package.json");
|
|
|
24
31
|
|
|
25
32
|
const readStdin = () => fs.readFileSync(0);
|
|
26
33
|
|
|
27
|
-
const indented =
|
|
34
|
+
const indented = (value) =>
|
|
35
|
+
JSON.stringify(value, null, 2).replaceAll("\n", "\n ");
|
|
28
36
|
|
|
29
37
|
function elapsed(since) {
|
|
30
38
|
const ms = Date.now() - since;
|
|
@@ -41,29 +49,47 @@ function elapsed(since) {
|
|
|
41
49
|
const session = (context, run) => attach(context).then(run);
|
|
42
50
|
|
|
43
51
|
export function printVersion() {
|
|
44
|
-
console.log(
|
|
52
|
+
console.log(
|
|
53
|
+
"swipt",
|
|
54
|
+
version,
|
|
55
|
+
`node ${process.versions.node}`,
|
|
56
|
+
`${process.platform}/${process.arch}`,
|
|
57
|
+
);
|
|
45
58
|
}
|
|
46
59
|
|
|
47
|
-
export const logs = context =>
|
|
48
|
-
session(context, async client => {
|
|
60
|
+
export const logs = (context) =>
|
|
61
|
+
session(context, async (client) => {
|
|
49
62
|
const { options } = context;
|
|
50
63
|
const levels = ["error", "warn", "info", "debug"];
|
|
51
64
|
const index = levels.indexOf(options.level);
|
|
52
65
|
if (index < 0) {
|
|
53
66
|
throw new UsageError("--level is error, warn, info or debug");
|
|
54
67
|
}
|
|
55
|
-
const request = {
|
|
68
|
+
const request = {
|
|
69
|
+
follow: options.follow,
|
|
70
|
+
tail: options.tail ?? 100,
|
|
71
|
+
swipletId: options.swiplet ?? "",
|
|
72
|
+
level: index + 1,
|
|
73
|
+
};
|
|
56
74
|
if (options.since > 0) {
|
|
57
75
|
request.since = timestampFromMs(Date.now() - options.since);
|
|
58
76
|
if (options.tail === undefined) {
|
|
59
77
|
request.tail = 0xffffffff;
|
|
60
78
|
}
|
|
61
79
|
}
|
|
62
|
-
for await (const response of client.logs.readLogs(request, {
|
|
80
|
+
for await (const response of client.logs.readLogs(request, {
|
|
81
|
+
signal: context.signal,
|
|
82
|
+
})) {
|
|
63
83
|
printLog(response.entry, true);
|
|
64
84
|
}
|
|
65
85
|
});
|
|
66
86
|
|
|
87
|
+
export const stop = (context) =>
|
|
88
|
+
session(context, async (client) => {
|
|
89
|
+
await client.system.shutdown({}, { signal: context.signal });
|
|
90
|
+
console.log("stopped");
|
|
91
|
+
});
|
|
92
|
+
|
|
67
93
|
function readInput(value) {
|
|
68
94
|
if (value === undefined || value === "") {
|
|
69
95
|
return undefined;
|
|
@@ -85,14 +111,21 @@ function readInput(value) {
|
|
|
85
111
|
}
|
|
86
112
|
}
|
|
87
113
|
|
|
88
|
-
const serviceStatus = state =>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
const serviceStatus = (state) =>
|
|
115
|
+
state.status === ServiceStatus.UNSPECIFIED
|
|
116
|
+
? "stopped"
|
|
117
|
+
: enumText(ServiceStatusSchema, state.status, "SERVICE_STATUS_");
|
|
118
|
+
|
|
119
|
+
const notInstalled = (id) =>
|
|
120
|
+
new Error(`there is no swiplet ${JSON.stringify(id)}`);
|
|
121
|
+
|
|
122
|
+
export const list = (context) =>
|
|
123
|
+
session(context, async (client) => {
|
|
124
|
+
const { swiplets } = await client.swiplets.listSwiplets(
|
|
125
|
+
{},
|
|
126
|
+
{ signal: context.signal },
|
|
127
|
+
);
|
|
128
|
+
const rows = swiplets.map((swiplet) => {
|
|
96
129
|
let service = "";
|
|
97
130
|
let status = "";
|
|
98
131
|
if (swiplet.service) {
|
|
@@ -102,15 +135,30 @@ export const list = context =>
|
|
|
102
135
|
status += `: ${swiplet.service.error.name}: ${swiplet.service.error.message}`;
|
|
103
136
|
}
|
|
104
137
|
}
|
|
105
|
-
return [
|
|
138
|
+
return [
|
|
139
|
+
swiplet.id,
|
|
140
|
+
swiplet.title,
|
|
141
|
+
swiplet.version,
|
|
142
|
+
swiplet.actions.map((action) => action.name).join(","),
|
|
143
|
+
service,
|
|
144
|
+
status,
|
|
145
|
+
];
|
|
106
146
|
});
|
|
107
|
-
console.log(
|
|
147
|
+
console.log(
|
|
148
|
+
columns([
|
|
149
|
+
["ID", "TITLE", "VERSION", "ACTIONS", "SERVICE", "STATUS"],
|
|
150
|
+
...rows,
|
|
151
|
+
]),
|
|
152
|
+
);
|
|
108
153
|
});
|
|
109
154
|
|
|
110
|
-
export const show = context =>
|
|
111
|
-
session(context, async client => {
|
|
112
|
-
const { swiplets } = await client.swiplets.listSwiplets(
|
|
113
|
-
|
|
155
|
+
export const show = (context) =>
|
|
156
|
+
session(context, async (client) => {
|
|
157
|
+
const { swiplets } = await client.swiplets.listSwiplets(
|
|
158
|
+
{},
|
|
159
|
+
{ signal: context.signal },
|
|
160
|
+
);
|
|
161
|
+
const swiplet = swiplets.find((it) => it.id === context.args[0]);
|
|
114
162
|
if (!swiplet) {
|
|
115
163
|
throw notInstalled(context.args[0]);
|
|
116
164
|
}
|
|
@@ -123,7 +171,9 @@ export const show = context =>
|
|
|
123
171
|
}
|
|
124
172
|
for (const action of swiplet.actions) {
|
|
125
173
|
console.log();
|
|
126
|
-
console.log(
|
|
174
|
+
console.log(
|
|
175
|
+
`action ${action.name} ${JSON.stringify(action.title)}${action.exposedToShortcuts ? " (shortcuts)" : ""}`,
|
|
176
|
+
);
|
|
127
177
|
if (action.description !== "") {
|
|
128
178
|
console.log(` ${action.description}`);
|
|
129
179
|
}
|
|
@@ -136,12 +186,15 @@ export const show = context =>
|
|
|
136
186
|
}
|
|
137
187
|
});
|
|
138
188
|
|
|
139
|
-
export const call = context =>
|
|
140
|
-
session(context, async client => {
|
|
189
|
+
export const call = (context) =>
|
|
190
|
+
session(context, async (client) => {
|
|
141
191
|
const [id, action] = context.args;
|
|
142
192
|
const input = readInput(context.options.input);
|
|
143
193
|
let result;
|
|
144
|
-
for await (const response of client.swiplets.callAction(
|
|
194
|
+
for await (const response of client.swiplets.callAction(
|
|
195
|
+
{ swipletId: id, action, input },
|
|
196
|
+
{ signal: context.signal },
|
|
197
|
+
)) {
|
|
145
198
|
if (response.part.case === "log") {
|
|
146
199
|
printLog(response.part.value, false);
|
|
147
200
|
} else if (response.part.case === "result") {
|
|
@@ -149,7 +202,9 @@ export const call = context =>
|
|
|
149
202
|
}
|
|
150
203
|
}
|
|
151
204
|
if (result?.outcome.case === "output") {
|
|
152
|
-
console.log(
|
|
205
|
+
console.log(
|
|
206
|
+
JSON.stringify(toJson(ValueSchema, result.outcome.value), null, 2),
|
|
207
|
+
);
|
|
153
208
|
return;
|
|
154
209
|
}
|
|
155
210
|
if (result?.outcome.case === "error") {
|
|
@@ -159,15 +214,23 @@ export const call = context =>
|
|
|
159
214
|
});
|
|
160
215
|
|
|
161
216
|
async function watchServices(client, id, signal) {
|
|
162
|
-
for await (const response of client.swiplets.watchServices(
|
|
163
|
-
|
|
217
|
+
for await (const response of client.swiplets.watchServices(
|
|
218
|
+
{ swipletId: id },
|
|
219
|
+
{ signal },
|
|
220
|
+
)) {
|
|
221
|
+
console.log(
|
|
222
|
+
`${response.swipletId}: ${serviceText(response.swipletId, response.service)}`,
|
|
223
|
+
);
|
|
164
224
|
}
|
|
165
225
|
}
|
|
166
226
|
|
|
167
|
-
export const setService = enabled => context =>
|
|
168
|
-
session(context, async client => {
|
|
227
|
+
export const setService = (enabled) => (context) =>
|
|
228
|
+
session(context, async (client) => {
|
|
169
229
|
const id = context.args[0];
|
|
170
|
-
const response = await client.swiplets.setServiceEnabled(
|
|
230
|
+
const response = await client.swiplets.setServiceEnabled(
|
|
231
|
+
{ swipletId: id, enabled },
|
|
232
|
+
{ signal: context.signal },
|
|
233
|
+
);
|
|
171
234
|
if (context.options.watch) {
|
|
172
235
|
await watchServices(client, id, context.signal);
|
|
173
236
|
return;
|
|
@@ -175,17 +238,27 @@ export const setService = enabled => context =>
|
|
|
175
238
|
console.log(`${id}: ${serviceText(id, response.service)}`);
|
|
176
239
|
});
|
|
177
240
|
|
|
178
|
-
export const serviceWatch =
|
|
241
|
+
export const serviceWatch = (context) =>
|
|
242
|
+
session(context, (client) =>
|
|
243
|
+
watchServices(client, context.args[0] ?? "", context.signal),
|
|
244
|
+
);
|
|
179
245
|
|
|
180
|
-
export const remove = context =>
|
|
181
|
-
session(context, async client => {
|
|
182
|
-
await client.swiplets.removeSwiplet(
|
|
246
|
+
export const remove = (context) =>
|
|
247
|
+
session(context, async (client) => {
|
|
248
|
+
await client.swiplets.removeSwiplet(
|
|
249
|
+
{ swipletId: context.args[0] },
|
|
250
|
+
{ signal: context.signal },
|
|
251
|
+
);
|
|
183
252
|
console.log("removed", context.args[0]);
|
|
184
253
|
});
|
|
185
254
|
|
|
186
|
-
const isLocal = name => {
|
|
255
|
+
const isLocal = (name) => {
|
|
187
256
|
const normalized = path.posix.normalize(name);
|
|
188
|
-
return
|
|
257
|
+
return (
|
|
258
|
+
!path.posix.isAbsolute(normalized) &&
|
|
259
|
+
normalized !== ".." &&
|
|
260
|
+
!normalized.startsWith("../")
|
|
261
|
+
);
|
|
189
262
|
};
|
|
190
263
|
|
|
191
264
|
class FileSink {
|
|
@@ -198,7 +271,9 @@ class FileSink {
|
|
|
198
271
|
|
|
199
272
|
target(name) {
|
|
200
273
|
if (!isLocal(name)) {
|
|
201
|
-
throw new Error(
|
|
274
|
+
throw new Error(
|
|
275
|
+
`the server sent the path ${name}, which leaves the output directory`,
|
|
276
|
+
);
|
|
202
277
|
}
|
|
203
278
|
return path.join(this.root, ...name.split("/"));
|
|
204
279
|
}
|
|
@@ -233,30 +308,44 @@ class FileSink {
|
|
|
233
308
|
}
|
|
234
309
|
}
|
|
235
310
|
|
|
236
|
-
const printSaved = (target, count) =>
|
|
311
|
+
const printSaved = (target, count) =>
|
|
312
|
+
console.error(`saved ${count} file(s) to ${target}`);
|
|
237
313
|
|
|
238
|
-
const dataCommands = target => ({
|
|
239
|
-
list: context =>
|
|
240
|
-
session(context, async client => {
|
|
314
|
+
const dataCommands = (target) => ({
|
|
315
|
+
list: (context) =>
|
|
316
|
+
session(context, async (client) => {
|
|
241
317
|
const {
|
|
242
318
|
id,
|
|
243
319
|
args: [directory = ""],
|
|
244
320
|
} = target(context.args);
|
|
245
|
-
const { files } = await client.swiplets.listDataFiles(
|
|
246
|
-
|
|
321
|
+
const { files } = await client.swiplets.listDataFiles(
|
|
322
|
+
{
|
|
323
|
+
swipletId: id,
|
|
324
|
+
path: directory,
|
|
325
|
+
recursive: context.options.recursive,
|
|
326
|
+
},
|
|
327
|
+
{ signal: context.signal },
|
|
328
|
+
);
|
|
329
|
+
const rows = files.map((file) => [
|
|
330
|
+
file.directory ? "-" : String(file.size),
|
|
331
|
+
dateTime(file.modified),
|
|
332
|
+
file.directory ? `${file.path}/` : file.path,
|
|
333
|
+
]);
|
|
247
334
|
if (rows.length > 0) {
|
|
248
335
|
console.log(columns(rows));
|
|
249
336
|
}
|
|
250
337
|
}),
|
|
251
|
-
read: context =>
|
|
252
|
-
session(context, async client => {
|
|
338
|
+
read: (context) =>
|
|
339
|
+
session(context, async (client) => {
|
|
253
340
|
const {
|
|
254
341
|
id,
|
|
255
342
|
where,
|
|
256
343
|
args: [given],
|
|
257
344
|
} = target(context.args);
|
|
258
345
|
const output = context.options.output ?? "";
|
|
259
|
-
const requested = path.posix
|
|
346
|
+
const requested = path.posix
|
|
347
|
+
.normalize(`/${given}`)
|
|
348
|
+
.replace(/^\/+|\/+$/g, "");
|
|
260
349
|
const printing = output === "" || output === "-";
|
|
261
350
|
const directory = () =>
|
|
262
351
|
new UsageError(
|
|
@@ -264,12 +353,16 @@ const dataCommands = target => ({
|
|
|
264
353
|
? `${JSON.stringify(given)} names ${where}; save it with --output DIRECTORY`
|
|
265
354
|
: `${JSON.stringify(requested)} is a directory in ${where}; save it with --output DIRECTORY`,
|
|
266
355
|
);
|
|
267
|
-
const relativeTo = name =>
|
|
356
|
+
const relativeTo = (name) =>
|
|
357
|
+
name.slice(requested.length).replace(/^\//, "");
|
|
268
358
|
let sink;
|
|
269
359
|
let single;
|
|
270
360
|
const contents = [];
|
|
271
361
|
try {
|
|
272
|
-
for await (const response of client.swiplets.readDataFile(
|
|
362
|
+
for await (const response of client.swiplets.readDataFile(
|
|
363
|
+
{ swipletId: id, path: given },
|
|
364
|
+
{ signal: context.signal },
|
|
365
|
+
)) {
|
|
273
366
|
if (response.part.case === "file") {
|
|
274
367
|
const file = response.part.value;
|
|
275
368
|
if (file.path === requested && !file.directory) {
|
|
@@ -290,7 +383,9 @@ const dataCommands = target => ({
|
|
|
290
383
|
continue;
|
|
291
384
|
}
|
|
292
385
|
if (!sink) {
|
|
293
|
-
throw new Error(
|
|
386
|
+
throw new Error(
|
|
387
|
+
`the server sent data for ${chunk.path} before announcing it`,
|
|
388
|
+
);
|
|
294
389
|
}
|
|
295
390
|
sink.write(relativeTo(chunk.path), chunk.offset, chunk.data);
|
|
296
391
|
}
|
|
@@ -316,56 +411,90 @@ const dataCommands = target => ({
|
|
|
316
411
|
return;
|
|
317
412
|
}
|
|
318
413
|
let destination = output;
|
|
319
|
-
if (
|
|
414
|
+
if (
|
|
415
|
+
fs.existsSync(destination) &&
|
|
416
|
+
fs.statSync(destination).isDirectory()
|
|
417
|
+
) {
|
|
320
418
|
destination = path.join(destination, path.posix.basename(single.path));
|
|
321
419
|
}
|
|
322
420
|
fs.writeFileSync(destination, data);
|
|
323
421
|
printSaved(destination, 1);
|
|
324
422
|
}),
|
|
325
|
-
write: context =>
|
|
326
|
-
session(context, async client => {
|
|
423
|
+
write: (context) =>
|
|
424
|
+
session(context, async (client) => {
|
|
327
425
|
const {
|
|
328
426
|
id,
|
|
329
427
|
args: [name, file],
|
|
330
428
|
} = target(context.args);
|
|
331
|
-
const data =
|
|
429
|
+
const data =
|
|
430
|
+
file === undefined || file === "-"
|
|
431
|
+
? readStdin()
|
|
432
|
+
: fs.readFileSync(file);
|
|
332
433
|
await client.swiplets.writeDataFile(
|
|
333
434
|
(async function* () {
|
|
334
|
-
yield {
|
|
435
|
+
yield {
|
|
436
|
+
part: { case: "header", value: { swipletId: id, path: name } },
|
|
437
|
+
};
|
|
335
438
|
for (let offset = 0; offset < data.length; offset += uploadChunk) {
|
|
336
|
-
yield {
|
|
439
|
+
yield {
|
|
440
|
+
part: {
|
|
441
|
+
case: "data",
|
|
442
|
+
value: data.subarray(offset, offset + uploadChunk),
|
|
443
|
+
},
|
|
444
|
+
};
|
|
337
445
|
}
|
|
338
446
|
})(),
|
|
339
447
|
{ signal: context.signal },
|
|
340
448
|
);
|
|
341
449
|
}),
|
|
342
|
-
remove: context =>
|
|
343
|
-
session(context, async client => {
|
|
450
|
+
remove: (context) =>
|
|
451
|
+
session(context, async (client) => {
|
|
344
452
|
const {
|
|
345
453
|
id,
|
|
346
454
|
args: [name],
|
|
347
455
|
} = target(context.args);
|
|
348
|
-
await client.swiplets.removeDataFile(
|
|
456
|
+
await client.swiplets.removeDataFile(
|
|
457
|
+
{ swipletId: id, path: name, recursive: context.options.recursive },
|
|
458
|
+
{ signal: context.signal },
|
|
459
|
+
);
|
|
349
460
|
}),
|
|
350
|
-
clear: context =>
|
|
351
|
-
session(context, async client => {
|
|
461
|
+
clear: (context) =>
|
|
462
|
+
session(context, async (client) => {
|
|
352
463
|
const { id } = target(context.args);
|
|
353
|
-
const { files } = await client.swiplets.listDataFiles(
|
|
464
|
+
const { files } = await client.swiplets.listDataFiles(
|
|
465
|
+
{ swipletId: id },
|
|
466
|
+
{ signal: context.signal },
|
|
467
|
+
);
|
|
354
468
|
for (const file of files) {
|
|
355
|
-
await client.swiplets.removeDataFile(
|
|
469
|
+
await client.swiplets.removeDataFile(
|
|
470
|
+
{ swipletId: id, path: file.path, recursive: true },
|
|
471
|
+
{ signal: context.signal },
|
|
472
|
+
);
|
|
356
473
|
}
|
|
357
474
|
}),
|
|
358
475
|
});
|
|
359
476
|
|
|
360
|
-
export const swipletData = dataCommands(([id, ...args]) => ({
|
|
477
|
+
export const swipletData = dataCommands(([id, ...args]) => ({
|
|
478
|
+
id,
|
|
479
|
+
where: `the data directory of ${id}`,
|
|
480
|
+
args,
|
|
481
|
+
}));
|
|
361
482
|
|
|
362
|
-
export const replData = dataCommands(args => ({
|
|
483
|
+
export const replData = dataCommands((args) => ({
|
|
484
|
+
id: "@repl",
|
|
485
|
+
where: "the data directory of the REPL",
|
|
486
|
+
args,
|
|
487
|
+
}));
|
|
363
488
|
|
|
364
489
|
async function deploy(client, archive, signal) {
|
|
365
490
|
const data = fs.readFileSync(archive);
|
|
366
491
|
return client.swiplets.deploySwiplet(
|
|
367
492
|
(async function* () {
|
|
368
|
-
for (
|
|
493
|
+
for (
|
|
494
|
+
let offset = 0;
|
|
495
|
+
offset < data.length || offset === 0;
|
|
496
|
+
offset += uploadChunk
|
|
497
|
+
) {
|
|
369
498
|
yield { chunk: data.subarray(offset, offset + uploadChunk) };
|
|
370
499
|
}
|
|
371
500
|
})(),
|
|
@@ -373,19 +502,28 @@ async function deploy(client, archive, signal) {
|
|
|
373
502
|
);
|
|
374
503
|
}
|
|
375
504
|
|
|
376
|
-
const printDeployed = (deployed, toStdout) =>
|
|
505
|
+
const printDeployed = (deployed, toStdout) =>
|
|
506
|
+
(toStdout ? console.log : console.error)(
|
|
507
|
+
deployed.replaced ? "replaced" : "installed",
|
|
508
|
+
deployed.swiplet.id,
|
|
509
|
+
deployed.swiplet.version,
|
|
510
|
+
);
|
|
377
511
|
|
|
378
512
|
export async function install(context) {
|
|
379
513
|
const [archive] = context.args;
|
|
380
514
|
if (!fs.existsSync(archive)) {
|
|
381
515
|
throw new Error(`there is no archive at ${archive}`);
|
|
382
516
|
}
|
|
383
|
-
await session(context, async
|
|
517
|
+
await session(context, async (client) =>
|
|
518
|
+
printDeployed(await deploy(client, archive, context.signal), true),
|
|
519
|
+
);
|
|
384
520
|
}
|
|
385
521
|
|
|
386
522
|
export async function deployProject(context) {
|
|
387
523
|
const { archive } = await buildProject(path.resolve(context.args[0] ?? "."));
|
|
388
|
-
await session(context, async
|
|
524
|
+
await session(context, async (client) =>
|
|
525
|
+
printDeployed(await deploy(client, archive, context.signal), true),
|
|
526
|
+
);
|
|
389
527
|
}
|
|
390
528
|
|
|
391
529
|
async function follow(signal, fatal, run) {
|
|
@@ -418,15 +556,26 @@ export async function develop(context) {
|
|
|
418
556
|
fatalReject = reject;
|
|
419
557
|
});
|
|
420
558
|
follow(inner, fatalReject, async () => {
|
|
421
|
-
for await (const response of client.swiplets.watchServices(
|
|
422
|
-
|
|
423
|
-
|
|
559
|
+
for await (const response of client.swiplets.watchServices(
|
|
560
|
+
{},
|
|
561
|
+
{ signal: inner },
|
|
562
|
+
)) {
|
|
563
|
+
if (
|
|
564
|
+
response.swipletId === project.config.id &&
|
|
565
|
+
response.service?.status === ServiceStatus.FAILED
|
|
566
|
+
) {
|
|
567
|
+
console.error(
|
|
568
|
+
`${response.swipletId}: ${serviceText(response.swipletId, response.service)}`,
|
|
569
|
+
);
|
|
424
570
|
}
|
|
425
571
|
}
|
|
426
572
|
});
|
|
427
573
|
if (!context.options["no-logs"]) {
|
|
428
574
|
follow(inner, fatalReject, async () => {
|
|
429
|
-
for await (const response of client.logs.readLogs(
|
|
575
|
+
for await (const response of client.logs.readLogs(
|
|
576
|
+
{ swipletId: project.config.id, follow: true },
|
|
577
|
+
{ signal: inner },
|
|
578
|
+
)) {
|
|
430
579
|
printLog(response.entry, false);
|
|
431
580
|
}
|
|
432
581
|
});
|
|
@@ -444,7 +593,9 @@ export async function develop(context) {
|
|
|
444
593
|
return;
|
|
445
594
|
}
|
|
446
595
|
if (built.digest === deployed) {
|
|
447
|
-
console.error(
|
|
596
|
+
console.error(
|
|
597
|
+
`built in ${elapsed(started)}; it came out as deployed, so nothing was deployed`,
|
|
598
|
+
);
|
|
448
599
|
return;
|
|
449
600
|
}
|
|
450
601
|
let result;
|
|
@@ -461,7 +612,9 @@ export async function develop(context) {
|
|
|
461
612
|
}
|
|
462
613
|
deployed = built.digest;
|
|
463
614
|
printDeployed(result, false);
|
|
464
|
-
console.error(
|
|
615
|
+
console.error(
|
|
616
|
+
`built and deployed in ${elapsed(started)}; watching ${root}`,
|
|
617
|
+
);
|
|
465
618
|
};
|
|
466
619
|
const watch = () =>
|
|
467
620
|
new Promise((resolve, reject) => {
|
|
@@ -488,7 +641,7 @@ export async function develop(context) {
|
|
|
488
641
|
clearTimeout(timer);
|
|
489
642
|
timer = setTimeout(() => cycle().catch(reject), rebuildDelay);
|
|
490
643
|
});
|
|
491
|
-
watcher.on("error", error => printError(error, "watch the project"));
|
|
644
|
+
watcher.on("error", (error) => printError(error, "watch the project"));
|
|
492
645
|
inner.addEventListener(
|
|
493
646
|
"abort",
|
|
494
647
|
() => {
|
|
@@ -507,7 +660,7 @@ export async function develop(context) {
|
|
|
507
660
|
}
|
|
508
661
|
}
|
|
509
662
|
|
|
510
|
-
const isFile = name => {
|
|
663
|
+
const isFile = (name) => {
|
|
511
664
|
try {
|
|
512
665
|
return fs.statSync(name).isFile();
|
|
513
666
|
} catch {
|
|
@@ -515,17 +668,29 @@ const isFile = name => {
|
|
|
515
668
|
}
|
|
516
669
|
};
|
|
517
670
|
|
|
518
|
-
export const isProgram = first => first === "-" || isFile(first);
|
|
671
|
+
export const isProgram = (first) => first === "-" || isFile(first);
|
|
519
672
|
|
|
520
673
|
function readScript([first, ...args]) {
|
|
521
674
|
if (first === undefined || first === "-") {
|
|
522
|
-
return {
|
|
675
|
+
return {
|
|
676
|
+
code: readStdin().toString(),
|
|
677
|
+
args,
|
|
678
|
+
program: true,
|
|
679
|
+
file: "input.js",
|
|
680
|
+
};
|
|
523
681
|
}
|
|
524
682
|
if (isFile(first)) {
|
|
525
|
-
return {
|
|
683
|
+
return {
|
|
684
|
+
code: fs.readFileSync(first, "utf8"),
|
|
685
|
+
args,
|
|
686
|
+
program: true,
|
|
687
|
+
file: first,
|
|
688
|
+
};
|
|
526
689
|
}
|
|
527
690
|
if (args.length > 0) {
|
|
528
|
-
throw new UsageError(
|
|
691
|
+
throw new UsageError(
|
|
692
|
+
`${JSON.stringify(first)} is not a file, and CODE takes no ARG`,
|
|
693
|
+
);
|
|
529
694
|
}
|
|
530
695
|
return { code: first, args, program: false, file: "input.js" };
|
|
531
696
|
}
|
|
@@ -546,30 +711,44 @@ class ImageSink {
|
|
|
546
711
|
this.directory = fs.mkdtempSync(path.join(os.tmpdir(), "swipt-repl-"));
|
|
547
712
|
}
|
|
548
713
|
}
|
|
549
|
-
const name = path.join(
|
|
714
|
+
const name = path.join(
|
|
715
|
+
this.directory,
|
|
716
|
+
`image-${crypto.randomBytes(5).toString("hex")}.png`,
|
|
717
|
+
);
|
|
550
718
|
fs.writeFileSync(name, data);
|
|
551
719
|
return name;
|
|
552
720
|
}
|
|
553
721
|
}
|
|
554
722
|
|
|
555
|
-
export const api = context =>
|
|
556
|
-
session(context, async client => {
|
|
557
|
-
process.stdout.write(
|
|
723
|
+
export const api = (context) =>
|
|
724
|
+
session(context, async (client) => {
|
|
725
|
+
process.stdout.write(
|
|
726
|
+
(await client.repl.getDeclarations({}, { signal: context.signal }))
|
|
727
|
+
.typescript,
|
|
728
|
+
);
|
|
558
729
|
});
|
|
559
730
|
|
|
560
|
-
export const reset =
|
|
731
|
+
export const reset = (context) =>
|
|
732
|
+
session(context, (client) =>
|
|
733
|
+
client.repl.reset({}, { signal: context.signal }),
|
|
734
|
+
);
|
|
561
735
|
|
|
562
736
|
export async function run(context) {
|
|
563
737
|
const { args, options, signal } = context;
|
|
564
738
|
const script = readScript(args);
|
|
565
|
-
await session(context, async client => {
|
|
739
|
+
await session(context, async (client) => {
|
|
566
740
|
const images = new ImageSink(options.output);
|
|
567
741
|
let failure;
|
|
568
|
-
for await (const response of client.repl.execute(
|
|
742
|
+
for await (const response of client.repl.execute(
|
|
743
|
+
{ code: script.code, args: script.args, program: script.program },
|
|
744
|
+
{ signal },
|
|
745
|
+
)) {
|
|
569
746
|
switch (response.part.case) {
|
|
570
747
|
case "console": {
|
|
571
748
|
const output = response.part.value;
|
|
572
|
-
(output.level === LogLevel.ERROR || output.level === LogLevel.WARN
|
|
749
|
+
(output.level === LogLevel.ERROR || output.level === LogLevel.WARN
|
|
750
|
+
? console.error
|
|
751
|
+
: console.log)(output.text);
|
|
573
752
|
break;
|
|
574
753
|
}
|
|
575
754
|
case "value":
|
|
@@ -584,7 +763,12 @@ export async function run(context) {
|
|
|
584
763
|
}
|
|
585
764
|
}
|
|
586
765
|
if (failure) {
|
|
587
|
-
throw printScriptError({
|
|
766
|
+
throw printScriptError({
|
|
767
|
+
...failure,
|
|
768
|
+
stack: failure.stack.map((frame) =>
|
|
769
|
+
frame.file === "input.js" ? { ...frame, file: script.file } : frame,
|
|
770
|
+
),
|
|
771
|
+
});
|
|
588
772
|
}
|
|
589
773
|
});
|
|
590
774
|
}
|