@await-widget/runtime 0.0.47 → 0.0.49
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 +27 -57
- package/package.json +1 -1
package/bin/await-widget.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/* eslint-disable n/prefer-global/buffer, no-bitwise, unicorn/no-array-sort */
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
|
+
import {execFileSync} from 'node:child_process';
|
|
4
5
|
import fs from 'node:fs';
|
|
5
6
|
import http from 'node:http';
|
|
6
7
|
import os from 'node:os';
|
|
@@ -24,7 +25,6 @@ const crcTable = makeCrcTable();
|
|
|
24
25
|
const bridgeInfoDirectory = '.await';
|
|
25
26
|
const bridgeInfoFileName = 'bridge.json';
|
|
26
27
|
const singleWidgetPath = '.';
|
|
27
|
-
const widgetDirectoryError = 'Run await-widget from a package root or first-level widget folder whose package.json includes @await-widget/runtime.';
|
|
28
28
|
|
|
29
29
|
function main() {
|
|
30
30
|
const options = parseArgs(process.argv.slice(2));
|
|
@@ -138,16 +138,15 @@ function parseAppArgs(args) {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
async function startWorkspaceServer(options) {
|
|
141
|
-
|
|
141
|
+
const workspaceRoot = process.cwd();
|
|
142
|
+
let widgetRoot;
|
|
142
143
|
try {
|
|
143
|
-
|
|
144
|
+
widgetRoot = await selectWidgetRoot(workspaceRoot);
|
|
144
145
|
} catch (error) {
|
|
145
146
|
console.error(error.message);
|
|
146
147
|
process.exit(1);
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
const {packageRoot, widgetRoot} = roots;
|
|
150
|
-
|
|
151
150
|
const token = crypto.randomBytes(6).toString('hex');
|
|
152
151
|
const bridge = createBridgeState(widgetRoot);
|
|
153
152
|
const server = http.createServer((request, response) => {
|
|
@@ -161,7 +160,7 @@ async function startWorkspaceServer(options) {
|
|
|
161
160
|
server.listen(options.port, '0.0.0.0', () => {
|
|
162
161
|
const address = server.address();
|
|
163
162
|
const port = typeof address === 'object' && address ? address.port : options.port;
|
|
164
|
-
writeBridgeInfo(
|
|
163
|
+
writeBridgeInfo(workspaceRoot, port, token);
|
|
165
164
|
console.log(`Await computer connection serving ${widgetRoot}`);
|
|
166
165
|
printServerUrls(port, token);
|
|
167
166
|
console.log('Press Ctrl+C to stop.');
|
|
@@ -386,51 +385,29 @@ function widgetPathKey(widgets) {
|
|
|
386
385
|
return widgets.map(widget => widget.path).sort((left, right) => left.localeCompare(right)).join('\n');
|
|
387
386
|
}
|
|
388
387
|
|
|
389
|
-
function
|
|
388
|
+
function findBridgeRoot(start) {
|
|
390
389
|
let current = path.resolve(start);
|
|
391
390
|
while (true) {
|
|
392
|
-
|
|
393
|
-
if (fs.existsSync(candidate)) {
|
|
391
|
+
if (fs.existsSync(bridgeInfoPath(current))) {
|
|
394
392
|
return current;
|
|
395
393
|
}
|
|
396
394
|
|
|
397
395
|
const parent = path.dirname(current);
|
|
398
396
|
if (parent === current) {
|
|
399
|
-
|
|
397
|
+
throw new Error('Cannot find Await bridge info. Run npx await-widget first.');
|
|
400
398
|
}
|
|
401
399
|
|
|
402
400
|
current = parent;
|
|
403
401
|
}
|
|
404
402
|
}
|
|
405
403
|
|
|
406
|
-
|
|
407
|
-
const widgetRoot = path.resolve(start);
|
|
408
|
-
const packageRoot = findPackageRoot(widgetRoot);
|
|
409
|
-
if (
|
|
410
|
-
!packageRoot
|
|
411
|
-
|| !hasRuntimeDependency(packageRoot)
|
|
412
|
-
) {
|
|
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);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
return {packageRoot, widgetRoot};
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
function selectWidgetRoot(packageRoot) {
|
|
404
|
+
function selectWidgetRoot(directory) {
|
|
428
405
|
const options = [
|
|
429
|
-
{name: `${path.basename(
|
|
430
|
-
...fs.readdirSync(
|
|
431
|
-
.filter(entry => entry.isDirectory() &&
|
|
406
|
+
{name: `${path.basename(directory)} (current directory)`, path: directory},
|
|
407
|
+
...fs.readdirSync(directory, {withFileTypes: true})
|
|
408
|
+
.filter(entry => entry.isDirectory() && isSelectableDirectoryName(entry.name))
|
|
432
409
|
.sort((left, right) => left.name.localeCompare(right.name))
|
|
433
|
-
.map(entry => ({name: entry.name, path: path.join(
|
|
410
|
+
.map(entry => ({name: entry.name, path: path.join(directory, entry.name)})),
|
|
434
411
|
];
|
|
435
412
|
let selected = 0;
|
|
436
413
|
let rendered = false;
|
|
@@ -478,11 +455,6 @@ function selectWidgetRoot(packageRoot) {
|
|
|
478
455
|
});
|
|
479
456
|
}
|
|
480
457
|
|
|
481
|
-
function hasRuntimeDependency(packageRoot) {
|
|
482
|
-
const manifest = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf8'));
|
|
483
|
-
return Boolean(manifest.dependencies?.['@await-widget/runtime'] ?? manifest.devDependencies?.['@await-widget/runtime']);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
458
|
function listDesktopWidgets(root) {
|
|
487
459
|
return [{name: path.basename(root), path: singleWidgetPath}];
|
|
488
460
|
}
|
|
@@ -517,7 +489,7 @@ function safeWidgetPath(root, widgetPath, options = {}) {
|
|
|
517
489
|
return root;
|
|
518
490
|
}
|
|
519
491
|
|
|
520
|
-
function
|
|
492
|
+
function isSelectableDirectoryName(name) {
|
|
521
493
|
return Boolean(name) && !name.includes('/') && !name.includes('\\') && !isExcludedName(name);
|
|
522
494
|
}
|
|
523
495
|
|
|
@@ -765,19 +737,11 @@ function resolveBridgeUrl(options) {
|
|
|
765
737
|
return options.bridgeUrl;
|
|
766
738
|
}
|
|
767
739
|
|
|
768
|
-
const root =
|
|
769
|
-
if (!root) {
|
|
770
|
-
throw new Error('Cannot find package.json for Await bridge lookup.');
|
|
771
|
-
}
|
|
772
|
-
|
|
740
|
+
const root = findBridgeRoot(options.workspace ?? process.cwd());
|
|
773
741
|
return readBridgeUrl(bridgeInfoPath(root));
|
|
774
742
|
}
|
|
775
743
|
|
|
776
744
|
function readBridgeUrl(infoPath) {
|
|
777
|
-
if (!fs.existsSync(infoPath)) {
|
|
778
|
-
throw new Error('Cannot find Await bridge info. Run npx await-widget first.');
|
|
779
|
-
}
|
|
780
|
-
|
|
781
745
|
const info = JSON.parse(fs.readFileSync(infoPath, 'utf8'));
|
|
782
746
|
return info.bridgeUrl;
|
|
783
747
|
}
|
|
@@ -811,7 +775,8 @@ function appCommandResult(options, tool, result) {
|
|
|
811
775
|
}
|
|
812
776
|
|
|
813
777
|
function saveCapture(options, result) {
|
|
814
|
-
const
|
|
778
|
+
const workspace = path.resolve(options.workspace ?? process.cwd());
|
|
779
|
+
const root = options.bridgeUrl ? workspace : findBridgeRoot(workspace);
|
|
815
780
|
const directory = path.join(root, bridgeInfoDirectory, 'captures');
|
|
816
781
|
const name = safeCaptureFileName(String(result.widgetId ?? 'widget'));
|
|
817
782
|
const filePath = path.join(directory, `${name}-${Date.now()}.png`);
|
|
@@ -921,6 +886,10 @@ function printServerUrls(port, token) {
|
|
|
921
886
|
console.log('');
|
|
922
887
|
console.log(recommended.url);
|
|
923
888
|
console.log('');
|
|
889
|
+
if (process.platform === 'darwin') {
|
|
890
|
+
execFileSync('pbcopy', {input: recommended.url});
|
|
891
|
+
console.log('Connection URL copied to clipboard.');
|
|
892
|
+
}
|
|
924
893
|
}
|
|
925
894
|
|
|
926
895
|
if (otherUrls.length > 0) {
|
|
@@ -1016,14 +985,15 @@ function printHelp() {
|
|
|
1016
985
|
await-widget [--port ${defaultPort}]
|
|
1017
986
|
await-widget app <command> [options]
|
|
1018
987
|
|
|
1019
|
-
Start the Await computer connection from
|
|
1020
|
-
|
|
1021
|
-
|
|
988
|
+
Start the Await computer connection from any directory. Choose the current
|
|
989
|
+
directory or one of its direct subdirectories. No package.json or runtime
|
|
990
|
+
dependency is required to start the connection.
|
|
1022
991
|
|
|
1023
992
|
What it does:
|
|
1024
993
|
- Serves the selected widget folder to Await for live sync.
|
|
1025
994
|
- Prints a URL to paste into Await's Connect Computer sheet.
|
|
1026
|
-
- Writes .await/bridge.json in the
|
|
995
|
+
- Writes .await/bridge.json in the directory where the connection was started.
|
|
996
|
+
- App commands search the current directory and its parents for bridge info.
|
|
1027
997
|
- Sends one-shot JSON app commands with await-widget app <command>.
|
|
1028
998
|
|
|
1029
999
|
Examples:
|
|
@@ -1035,7 +1005,7 @@ Examples:
|
|
|
1035
1005
|
npx await-widget app get-recent-widget-logs --widget-id YourWidget
|
|
1036
1006
|
|
|
1037
1007
|
App command options:
|
|
1038
|
-
--workspace <path>
|
|
1008
|
+
--workspace <path> Search this directory and its parents for .await/bridge.json.
|
|
1039
1009
|
--bridge-url <url> Send directly to a bridge URL instead of reading bridge.json.
|
|
1040
1010
|
--json <json> Merge raw JSON arguments into the app command.
|
|
1041
1011
|
|