@await-widget/runtime 0.0.31 → 0.0.32
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/bin/await-widget.js +72 -10
- package/package.json +1 -1
package/bin/await-widget.js
CHANGED
|
@@ -6,6 +6,7 @@ import http from 'node:http';
|
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import process from 'node:process';
|
|
9
|
+
import readline from 'node:readline';
|
|
9
10
|
|
|
10
11
|
const defaultPort = 4343;
|
|
11
12
|
const maxBodyBytes = 100 * 1024 * 1024;
|
|
@@ -16,6 +17,7 @@ const crcTable = makeCrcTable();
|
|
|
16
17
|
const bridgeInfoDirectory = '.await';
|
|
17
18
|
const bridgeInfoFileName = 'bridge.json';
|
|
18
19
|
const singleWidgetPath = '.';
|
|
20
|
+
const widgetDirectoryError = 'Run await-widget from a package root or first-level widget folder whose package.json includes @await-widget/runtime.';
|
|
19
21
|
|
|
20
22
|
function main() {
|
|
21
23
|
const options = parseArgs(process.argv.slice(2));
|
|
@@ -128,10 +130,10 @@ function parseAppArgs(args) {
|
|
|
128
130
|
};
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
function startWorkspaceServer(options) {
|
|
133
|
+
async function startWorkspaceServer(options) {
|
|
132
134
|
let roots;
|
|
133
135
|
try {
|
|
134
|
-
roots = resolveWidgetServerRoots(process.cwd());
|
|
136
|
+
roots = await resolveWidgetServerRoots(process.cwd());
|
|
135
137
|
} catch (error) {
|
|
136
138
|
console.error(error.message);
|
|
137
139
|
process.exit(1);
|
|
@@ -394,22 +396,81 @@ function findPackageRoot(start) {
|
|
|
394
396
|
}
|
|
395
397
|
}
|
|
396
398
|
|
|
397
|
-
function resolveWidgetServerRoots(start) {
|
|
399
|
+
async function resolveWidgetServerRoots(start) {
|
|
398
400
|
const widgetRoot = path.resolve(start);
|
|
399
401
|
const packageRoot = findPackageRoot(widgetRoot);
|
|
400
402
|
if (
|
|
401
403
|
!packageRoot
|
|
402
|
-
|| packageRoot === widgetRoot
|
|
403
|
-
|| path.dirname(widgetRoot) !== packageRoot
|
|
404
|
-
|| !isValidTopLevelName(path.basename(widgetRoot))
|
|
405
404
|
|| !hasRuntimeDependency(packageRoot)
|
|
406
405
|
) {
|
|
407
|
-
throw new Error(
|
|
406
|
+
throw new Error(widgetDirectoryError);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (packageRoot === widgetRoot) {
|
|
410
|
+
return {packageRoot, widgetRoot: await selectWidgetRoot(packageRoot)};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (path.dirname(widgetRoot) !== packageRoot || !isValidTopLevelName(path.basename(widgetRoot))) {
|
|
414
|
+
throw new Error(widgetDirectoryError);
|
|
408
415
|
}
|
|
409
416
|
|
|
410
417
|
return {packageRoot, widgetRoot};
|
|
411
418
|
}
|
|
412
419
|
|
|
420
|
+
function selectWidgetRoot(packageRoot) {
|
|
421
|
+
const options = [
|
|
422
|
+
{name: `${path.basename(packageRoot)} (root)`, path: packageRoot},
|
|
423
|
+
...fs.readdirSync(packageRoot, {withFileTypes: true})
|
|
424
|
+
.filter(entry => entry.isDirectory() && isValidTopLevelName(entry.name))
|
|
425
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
426
|
+
.map(entry => ({name: entry.name, path: path.join(packageRoot, entry.name)})),
|
|
427
|
+
];
|
|
428
|
+
let selected = 0;
|
|
429
|
+
let rendered = false;
|
|
430
|
+
readline.emitKeypressEvents(process.stdin);
|
|
431
|
+
process.stdin.setRawMode(true);
|
|
432
|
+
process.stdin.resume();
|
|
433
|
+
console.log('Select a directory to connect:');
|
|
434
|
+
|
|
435
|
+
const render = () => {
|
|
436
|
+
if (rendered) {
|
|
437
|
+
readline.moveCursor(process.stdout, 0, -options.length);
|
|
438
|
+
readline.clearScreenDown(process.stdout);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
process.stdout.write(`${options.map((option, index) => `${index === selected ? '❯' : ' '} ${option.name}`).join('\n')}\n`);
|
|
442
|
+
rendered = true;
|
|
443
|
+
};
|
|
444
|
+
render();
|
|
445
|
+
|
|
446
|
+
return new Promise(resolve => {
|
|
447
|
+
const cleanup = () => {
|
|
448
|
+
process.stdin.off('keypress', onKeypress);
|
|
449
|
+
process.stdin.setRawMode(false);
|
|
450
|
+
process.stdin.pause();
|
|
451
|
+
};
|
|
452
|
+
const onKeypress = (_character, key) => {
|
|
453
|
+
if (key.name === 'up' || key.name === 'down') {
|
|
454
|
+
selected = (selected + (key.name === 'up' ? options.length - 1 : 1)) % options.length;
|
|
455
|
+
render();
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
460
|
+
cleanup();
|
|
461
|
+
resolve(options[selected].path);
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (key.ctrl && key.name === 'c') {
|
|
466
|
+
cleanup();
|
|
467
|
+
process.exit(130);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
process.stdin.on('keypress', onKeypress);
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
|
|
413
474
|
function hasRuntimeDependency(packageRoot) {
|
|
414
475
|
const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
415
476
|
return Boolean(manifest.dependencies?.['@await-widget/runtime'] ?? manifest.devDependencies?.['@await-widget/runtime']);
|
|
@@ -948,11 +1009,12 @@ function printHelp() {
|
|
|
948
1009
|
await-widget [--port ${defaultPort}]
|
|
949
1010
|
await-widget app <command> [options]
|
|
950
1011
|
|
|
951
|
-
Start the Await computer connection from a first-level widget
|
|
952
|
-
|
|
1012
|
+
Start the Await computer connection from a package root or first-level widget
|
|
1013
|
+
folder whose package.json includes @await-widget/runtime. Starting from the
|
|
1014
|
+
package root opens a directory selector.
|
|
953
1015
|
|
|
954
1016
|
What it does:
|
|
955
|
-
- Serves the
|
|
1017
|
+
- Serves the selected widget folder to Await for live sync.
|
|
956
1018
|
- Prints a URL to paste into Await's Connect Computer sheet.
|
|
957
1019
|
- Writes .await/bridge.json in the package root for app commands.
|
|
958
1020
|
- Sends one-shot JSON app commands with await-widget app <command>.
|