@await-widget/runtime 0.0.31 → 0.0.33
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 +81 -12
- package/package.json +1 -1
package/bin/await-widget.js
CHANGED
|
@@ -6,16 +6,25 @@ 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;
|
|
12
13
|
const zipDosTime = 0;
|
|
13
14
|
const zipDosDate = 33;
|
|
14
|
-
const excludedNames = new Set([
|
|
15
|
+
const excludedNames = new Set([
|
|
16
|
+
'node_modules',
|
|
17
|
+
'package.json',
|
|
18
|
+
'package-lock.json',
|
|
19
|
+
'tsconfig.json',
|
|
20
|
+
'xo.config.js',
|
|
21
|
+
]);
|
|
22
|
+
const excludedSuffixes = ['.lock', '.lockb', '.yaml', '.yml', '.toml'];
|
|
15
23
|
const crcTable = makeCrcTable();
|
|
16
24
|
const bridgeInfoDirectory = '.await';
|
|
17
25
|
const bridgeInfoFileName = 'bridge.json';
|
|
18
26
|
const singleWidgetPath = '.';
|
|
27
|
+
const widgetDirectoryError = 'Run await-widget from a package root or first-level widget folder whose package.json includes @await-widget/runtime.';
|
|
19
28
|
|
|
20
29
|
function main() {
|
|
21
30
|
const options = parseArgs(process.argv.slice(2));
|
|
@@ -128,10 +137,10 @@ function parseAppArgs(args) {
|
|
|
128
137
|
};
|
|
129
138
|
}
|
|
130
139
|
|
|
131
|
-
function startWorkspaceServer(options) {
|
|
140
|
+
async function startWorkspaceServer(options) {
|
|
132
141
|
let roots;
|
|
133
142
|
try {
|
|
134
|
-
roots = resolveWidgetServerRoots(process.cwd());
|
|
143
|
+
roots = await resolveWidgetServerRoots(process.cwd());
|
|
135
144
|
} catch (error) {
|
|
136
145
|
console.error(error.message);
|
|
137
146
|
process.exit(1);
|
|
@@ -394,22 +403,81 @@ function findPackageRoot(start) {
|
|
|
394
403
|
}
|
|
395
404
|
}
|
|
396
405
|
|
|
397
|
-
function resolveWidgetServerRoots(start) {
|
|
406
|
+
async function resolveWidgetServerRoots(start) {
|
|
398
407
|
const widgetRoot = path.resolve(start);
|
|
399
408
|
const packageRoot = findPackageRoot(widgetRoot);
|
|
400
409
|
if (
|
|
401
410
|
!packageRoot
|
|
402
|
-
|| packageRoot === widgetRoot
|
|
403
|
-
|| path.dirname(widgetRoot) !== packageRoot
|
|
404
|
-
|| !isValidTopLevelName(path.basename(widgetRoot))
|
|
405
411
|
|| !hasRuntimeDependency(packageRoot)
|
|
406
412
|
) {
|
|
407
|
-
throw new Error(
|
|
413
|
+
throw new Error(widgetDirectoryError);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (packageRoot === widgetRoot) {
|
|
417
|
+
return {packageRoot, widgetRoot: await selectWidgetRoot(packageRoot)};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (path.dirname(widgetRoot) !== packageRoot || !isValidTopLevelName(path.basename(widgetRoot))) {
|
|
421
|
+
throw new Error(widgetDirectoryError);
|
|
408
422
|
}
|
|
409
423
|
|
|
410
424
|
return {packageRoot, widgetRoot};
|
|
411
425
|
}
|
|
412
426
|
|
|
427
|
+
function selectWidgetRoot(packageRoot) {
|
|
428
|
+
const options = [
|
|
429
|
+
{name: `${path.basename(packageRoot)} (root)`, path: packageRoot},
|
|
430
|
+
...fs.readdirSync(packageRoot, {withFileTypes: true})
|
|
431
|
+
.filter(entry => entry.isDirectory() && isValidTopLevelName(entry.name))
|
|
432
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
433
|
+
.map(entry => ({name: entry.name, path: path.join(packageRoot, entry.name)})),
|
|
434
|
+
];
|
|
435
|
+
let selected = 0;
|
|
436
|
+
let rendered = false;
|
|
437
|
+
readline.emitKeypressEvents(process.stdin);
|
|
438
|
+
process.stdin.setRawMode(true);
|
|
439
|
+
process.stdin.resume();
|
|
440
|
+
console.log('Select a directory to connect:');
|
|
441
|
+
|
|
442
|
+
const render = () => {
|
|
443
|
+
if (rendered) {
|
|
444
|
+
readline.moveCursor(process.stdout, 0, -options.length);
|
|
445
|
+
readline.clearScreenDown(process.stdout);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
process.stdout.write(`${options.map((option, index) => `${index === selected ? '❯' : ' '} ${option.name}`).join('\n')}\n`);
|
|
449
|
+
rendered = true;
|
|
450
|
+
};
|
|
451
|
+
render();
|
|
452
|
+
|
|
453
|
+
return new Promise(resolve => {
|
|
454
|
+
const cleanup = () => {
|
|
455
|
+
process.stdin.off('keypress', onKeypress);
|
|
456
|
+
process.stdin.setRawMode(false);
|
|
457
|
+
process.stdin.pause();
|
|
458
|
+
};
|
|
459
|
+
const onKeypress = (_character, key) => {
|
|
460
|
+
if (key.name === 'up' || key.name === 'down') {
|
|
461
|
+
selected = (selected + (key.name === 'up' ? options.length - 1 : 1)) % options.length;
|
|
462
|
+
render();
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if (key.name === 'return' || key.name === 'enter') {
|
|
467
|
+
cleanup();
|
|
468
|
+
resolve(options[selected].path);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (key.ctrl && key.name === 'c') {
|
|
473
|
+
cleanup();
|
|
474
|
+
process.exit(130);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
process.stdin.on('keypress', onKeypress);
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
413
481
|
function hasRuntimeDependency(packageRoot) {
|
|
414
482
|
const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
415
483
|
return Boolean(manifest.dependencies?.['@await-widget/runtime'] ?? manifest.devDependencies?.['@await-widget/runtime']);
|
|
@@ -420,7 +488,7 @@ function listDesktopWidgets(root) {
|
|
|
420
488
|
}
|
|
421
489
|
|
|
422
490
|
function isExcludedName(name) {
|
|
423
|
-
return name.startsWith('.') || excludedNames.has(name);
|
|
491
|
+
return name.startsWith('.') || excludedNames.has(name) || excludedSuffixes.some(suffix => name.endsWith(suffix));
|
|
424
492
|
}
|
|
425
493
|
|
|
426
494
|
function widgetRootFromQuery(root, url) {
|
|
@@ -948,11 +1016,12 @@ function printHelp() {
|
|
|
948
1016
|
await-widget [--port ${defaultPort}]
|
|
949
1017
|
await-widget app <command> [options]
|
|
950
1018
|
|
|
951
|
-
Start the Await computer connection from a first-level widget
|
|
952
|
-
|
|
1019
|
+
Start the Await computer connection from a package root or first-level widget
|
|
1020
|
+
folder whose package.json includes @await-widget/runtime. Starting from the
|
|
1021
|
+
package root opens a directory selector.
|
|
953
1022
|
|
|
954
1023
|
What it does:
|
|
955
|
-
- Serves the
|
|
1024
|
+
- Serves the selected widget folder to Await for live sync.
|
|
956
1025
|
- Prints a URL to paste into Await's Connect Computer sheet.
|
|
957
1026
|
- Writes .await/bridge.json in the package root for app commands.
|
|
958
1027
|
- Sends one-shot JSON app commands with await-widget app <command>.
|