@glasshome/widget-cli 0.11.0 → 0.11.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glasshome/widget-cli",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "description": "CLI for creating and managing GlassHome widgets",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "@types/bun": "latest",
22
22
  "@types/semver": "^7.0.0",
23
23
  "playwright": "^1.40.0",
24
- "typescript": "^5"
24
+ "typescript": "^7.0.2"
25
25
  },
26
26
  "dependencies": {
27
27
  "@clack/prompts": "^1.6.0",
@@ -30,7 +30,7 @@
30
30
  "@fontsource-variable/geist-mono": "^5.2.8",
31
31
  "@glasshome/sync-layer": "0.7.2",
32
32
  "@glasshome/widget-contract": "0.2.0",
33
- "@glasshome/widget-sdk": "1.10.3",
33
+ "@glasshome/widget-sdk": "1.11.1",
34
34
  "@iconify-json/lucide": "^1.2.0",
35
35
  "@iconify-json/mdi": "^1.2.3",
36
36
  "@tailwindcss/vite": "^4.1.13",
@@ -2,7 +2,7 @@ import { existsSync, readdirSync, readFileSync, statSync, watch } from "node:fs"
2
2
  import { resolve } from "node:path";
3
3
  import { log, note, spinner } from "@clack/prompts";
4
4
  import color from "picocolors";
5
- import { buildWidgets } from "@glasshome/widget-sdk/vite";
5
+ import { buildWidgets, createIntrospectSession } from "@glasshome/widget-sdk/vite";
6
6
  import { trpcMutate, trpcQuery } from "../utils/api";
7
7
  import { clearHostToken, extractHost, getHostToken, storeHostToken } from "../utils/auth";
8
8
  import { lintAndReport } from "../utils/lint-source";
@@ -348,6 +348,9 @@ export async function runConnect(
348
348
  const pending = new Set<string>();
349
349
  let debounceTimer: ReturnType<typeof setTimeout> | null = null;
350
350
  let buildInFlight = false;
351
+ // One worker for the whole session: a fresh introspection process per save is
352
+ // the boot tax this avoids (docs/superpowers/specs/2026-08-18-widget-sdk-persistent-introspect-worker-design.md).
353
+ const introspectSession = createIntrospectSession();
351
354
 
352
355
  async function flush(): Promise<void> {
353
356
  debounceTimer = null;
@@ -362,7 +365,9 @@ export async function runConnect(
362
365
  const origCwd = process.cwd();
363
366
  process.chdir(cwd);
364
367
  try {
365
- await withQuietStdout(() => buildWidgets({ ...buildOpts, only: widgets }));
368
+ await withQuietStdout(() =>
369
+ buildWidgets({ ...buildOpts, only: widgets, session: introspectSession }),
370
+ );
366
371
  } finally {
367
372
  process.chdir(origCwd);
368
373
  }
@@ -421,6 +426,9 @@ export async function runConnect(
421
426
  log.info("Disconnecting...");
422
427
  if (debounceTimer) clearTimeout(debounceTimer);
423
428
  watcher.close();
429
+ // connect never exits normally, so without this the worker only dies via
430
+ // its stdin-EOF watchdog.
431
+ await introspectSession.dispose();
424
432
 
425
433
  for (const slug of registeredTags) {
426
434
  try {
@@ -21,14 +21,8 @@ export async function runPreview(cwd: string, names: string[], isolate: boolean)
21
21
  process.exit(1);
22
22
  }
23
23
 
24
- // Capture the REAL stdout writer before withQuietStdout no-ops
25
- // process.stdout.write. A clack spinner writes through that same override and
26
- // would freeze inside the quiet block, so progress goes out this bound
27
- // reference (which the override cannot intercept) as plain lines. Build/vite
28
- // noise stays silenced; only these phase lines get through.
29
- const realWrite = process.stdout.write.bind(process.stdout);
30
24
  const progress = (m: string) => {
31
- realWrite(`${color.gray("│")} ${color.dim(m)}\n`);
25
+ process.stdout.write(`${color.gray("│")} ${color.dim(m)}\n`);
32
26
  };
33
27
 
34
28
  log.info(names.length ? `Previewing ${names.join(", ")}` : "Previewing all widgets");
@@ -1,20 +1,24 @@
1
1
  /**
2
- * Run `fn` with stdout writes swallowed. `buildWidgets()` (SDK) console.logs a
2
+ * Run `fn` with console logging swallowed. `buildWidgets()` (SDK) logs a
3
3
  * "[registry] Generated..." line mid-build; when the caller drives a clack
4
- * spinner that raw write lands on the spinner's line and garbles it. Stderr is
5
- * left alone so real warnings/errors still surface.
4
+ * spinner that line lands on the spinner's line and garbles it.
5
+ *
6
+ * Only the console methods are silenced, never `process.stdout.write`: a clack
7
+ * spinner renders its frames through that write, so overriding it left every
8
+ * caller's spinner frozen for the whole build. Bun's console writes to fd 1
9
+ * natively and bypasses a `process.stdout.write` override anyway, so the
10
+ * console patch is the one that ever did the work. Stderr is left alone so real
11
+ * warnings and errors still surface.
6
12
  */
7
13
  export async function withQuietStdout<T>(fn: () => Promise<T>): Promise<T> {
8
- const originalWrite = process.stdout.write.bind(process.stdout);
9
14
  const originalLog = console.log;
10
- // Bun's console.log writes to fd 1 natively and bypasses a process.stdout.write
11
- // override, so both paths are silenced.
12
- process.stdout.write = (() => true) as typeof process.stdout.write;
15
+ const originalInfo = console.info;
13
16
  console.log = () => {};
17
+ console.info = () => {};
14
18
  try {
15
19
  return await fn();
16
20
  } finally {
17
- process.stdout.write = originalWrite;
18
21
  console.log = originalLog;
22
+ console.info = originalInfo;
19
23
  }
20
24
  }