@glasshome/widget-cli 0.4.11 → 0.4.13

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/cli.ts CHANGED
@@ -25,6 +25,7 @@ Commands:
25
25
  add Add a new widget to the project
26
26
  build Build all widgets (per-widget, self-contained bundles)
27
27
  connect <url> Connect to a running dashboard for live testing
28
+ --re-auth discards stored credentials and re-runs device approval
28
29
  validate [name] Validate all widgets or a specific one
29
30
  publish [hub-url] Build and publish a widget to Hub
30
31
  login [hub-url] Authenticate with GlassHome Hub
@@ -60,13 +61,19 @@ const { values: flags, positionals } = parseArgs({
60
61
  name: { type: "string" },
61
62
  bump: { type: "string" },
62
63
  scope: { type: "string" },
64
+ "re-auth": { type: "boolean" },
63
65
  help: { type: "boolean", short: "h" },
64
66
  },
65
67
  allowPositionals: true,
66
68
  strict: false,
67
69
  });
68
70
 
69
- const explicitDir = flags.dir;
71
+ // strict:false widens every flag to string | boolean | undefined; a bare
72
+ // `--flag` with no value parses as `true`, which no string option accepts.
73
+ const str = (v: string | boolean | undefined): string | undefined =>
74
+ typeof v === "string" ? v : undefined;
75
+
76
+ const explicitDir = str(flags.dir);
70
77
  const [command, ...args] = positionals;
71
78
 
72
79
  if (command === "help" || flags.help) {
@@ -114,7 +121,7 @@ switch (effectiveCommand) {
114
121
  process.exit(1);
115
122
  }
116
123
  const { runConnect } = await import("../src/commands/connect");
117
- await runConnect(url, resolveWidgetDir());
124
+ await runConnect(url, resolveWidgetDir(), { reAuth: flags["re-auth"] === true });
118
125
  break;
119
126
  }
120
127
 
@@ -144,9 +151,9 @@ switch (effectiveCommand) {
144
151
  const hubUrlArg = args[0];
145
152
  const { runPublish } = await import("../src/commands/publish");
146
153
  await runPublish(resolveWidgetDir(), hubUrlArg, {
147
- name: flags.name,
148
- bump: flags.bump as "keep" | "patch" | "minor" | "major" | undefined,
149
- scope: flags.scope,
154
+ name: str(flags.name),
155
+ bump: str(flags.bump) as "keep" | "patch" | "minor" | "major" | undefined,
156
+ scope: str(flags.scope),
150
157
  });
151
158
  outro("Done");
152
159
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glasshome/widget-cli",
3
- "version": "0.4.11",
3
+ "version": "0.4.13",
4
4
  "description": "CLI for creating and managing GlassHome widgets",
5
5
  "type": "module",
6
6
  "bin": {
@@ -87,7 +87,11 @@ async function uploadAllWidgets(apiUrl: string, distDir: string, token: string):
87
87
  return slugs;
88
88
  }
89
89
 
90
- export async function runConnect(apiUrl: string, cwd: string): Promise<void> {
90
+ export async function runConnect(
91
+ apiUrl: string,
92
+ cwd: string,
93
+ opts: { reAuth?: boolean } = {},
94
+ ): Promise<void> {
91
95
  const distDir = resolve(cwd, "dist");
92
96
  const solid = (await import("vite-plugin-solid")).default;
93
97
  const buildOpts = { srcDir: "src", outDir: "dist", plugins: [solid()] };
@@ -119,6 +123,11 @@ export async function runConnect(apiUrl: string, cwd: string): Promise<void> {
119
123
  const host = extractHost(api);
120
124
  let token = "";
121
125
 
126
+ if (opts.reAuth) {
127
+ clearHostToken(host);
128
+ log.info("Discarded stored credentials (--re-auth).");
129
+ }
130
+
122
131
  // Validate stored token before using it
123
132
  const existingToken = getHostToken(host);
124
133
  if (existingToken) {
@@ -216,19 +225,19 @@ export async function runConnect(apiUrl: string, cwd: string): Promise<void> {
216
225
  });
217
226
 
218
227
  if (res.ok) {
219
- // better-auth's device-authorization plugin returns a
220
- // first-party session, not an OIDC token bundle. The bearer is
221
- // session.token; expiry is session.expiresAt (ISO/epoch/Date).
228
+ // better-auth's device-authorization plugin returns an OAuth-style
229
+ // bundle: { access_token, token_type, expires_in, scope }. The
230
+ // access_token IS the first-party session token.
222
231
  const data = (await res.json()) as {
223
- session?: { token: string; expiresAt: string | number | Date };
224
- user?: unknown;
232
+ access_token?: string;
233
+ expires_in?: number;
225
234
  };
226
- if (!data.session?.token) {
235
+ if (!data.access_token) {
227
236
  s.stop("Auth response missing session token");
228
237
  break;
229
238
  }
230
- token = data.session.token;
231
- const tokenExpiresAt = new Date(data.session.expiresAt).getTime();
239
+ token = data.access_token;
240
+ const tokenExpiresAt = Date.now() + (data.expires_in ?? 0) * 1000;
232
241
  storeHostToken(host, token, tokenExpiresAt);
233
242
  break;
234
243
  }