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