@glasshome/widget-cli 0.4.5 → 0.4.7

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
@@ -43,6 +43,8 @@ Examples:
43
43
  glasshome-widget info
44
44
  glasshome-widget info clock
45
45
  glasshome-widget publish
46
+ glasshome-widget publish --name light --bump patch
47
+ glasshome-widget publish --name light --bump minor --scope glasshome
46
48
  glasshome-widget login
47
49
  glasshome-widget login https://my-hub.example.com
48
50
  glasshome-widget upgrade
@@ -130,9 +132,19 @@ switch (effectiveCommand) {
130
132
  }
131
133
 
132
134
  case "publish": {
133
- const hubUrlArg = args[0];
135
+ const hubUrlArg = args.find((a) => !a.startsWith("--"));
136
+ const nameIdx = rawArgs.indexOf("--name");
137
+ const bumpIdx = rawArgs.indexOf("--bump");
138
+ const scopeIdx = rawArgs.indexOf("--scope");
139
+ const pubName = nameIdx !== -1 ? rawArgs[nameIdx + 1] : undefined;
140
+ const pubBump = bumpIdx !== -1 ? rawArgs[bumpIdx + 1] : undefined;
141
+ const pubScope = scopeIdx !== -1 ? rawArgs[scopeIdx + 1] : undefined;
134
142
  const { runPublish } = await import("../src/commands/publish");
135
- await runPublish(resolveWidgetDir(), hubUrlArg);
143
+ await runPublish(resolveWidgetDir(), hubUrlArg, {
144
+ name: pubName,
145
+ bump: pubBump as "keep" | "patch" | "minor" | "major" | undefined,
146
+ scope: pubScope,
147
+ });
136
148
  outro("Done");
137
149
  break;
138
150
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glasshome/widget-cli",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "CLI for creating and managing GlassHome widgets",
5
5
  "type": "module",
6
6
  "bin": {
@@ -17,14 +17,14 @@
17
17
  ],
18
18
  "devDependencies": {
19
19
  "@types/bun": "latest",
20
- "@types/semver": "^7.0.0",
21
- "vite-plugin-solid": "^2.11.0"
20
+ "@types/semver": "^7.0.0"
22
21
  },
23
22
  "dependencies": {
24
23
  "@clack/prompts": "^0.10.0",
25
- "@glasshome/widget-sdk": "0.2.3",
24
+ "@glasshome/widget-sdk": "0.2.5",
26
25
  "open": "^11.0.0",
27
- "semver": "^7.6.0"
26
+ "semver": "^7.6.0",
27
+ "vite-plugin-solid": "^2.11.0"
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
@@ -14,7 +14,17 @@ import {
14
14
  } from "../utils/manifest";
15
15
  import { runLogin } from "./login";
16
16
 
17
- export async function runPublish(cwd: string, hubUrlOverride?: string): Promise<void> {
17
+ interface PublishOptions {
18
+ name?: string;
19
+ bump?: "keep" | "patch" | "minor" | "major";
20
+ scope?: string;
21
+ }
22
+
23
+ export async function runPublish(
24
+ cwd: string,
25
+ hubUrlOverride?: string,
26
+ options?: PublishOptions,
27
+ ): Promise<void> {
18
28
  const s = spinner();
19
29
 
20
30
  // Step 1: Validate (quiet)
@@ -53,7 +63,15 @@ export async function runPublish(cwd: string, hubUrlOverride?: string): Promise<
53
63
  }
54
64
 
55
65
  let scope: string;
56
- if (scopes.length === 1) {
66
+ if (options?.scope) {
67
+ const match = scopes.find((s) => s.name === options.scope);
68
+ if (!match) {
69
+ log.error(`Scope @${options.scope} not found. Available: ${scopes.map((s) => s.name).join(", ")}`);
70
+ process.exit(1);
71
+ }
72
+ scope = match.name;
73
+ log.info(`Publishing as @${scope} (${match.type})`);
74
+ } else if (scopes.length === 1) {
57
75
  const only = scopes[0]!;
58
76
  scope = only.name;
59
77
  log.info(`Publishing as @${scope} (${only.type})`);
@@ -76,48 +94,65 @@ export async function runPublish(cwd: string, hubUrlOverride?: string): Promise<
76
94
 
77
95
  // Step 4: Select widget
78
96
  const widgets = discoverWidgets(cwd);
79
- const widgetOptions = widgets.map((name) => {
80
- const manifest = readManifest(cwd, name);
81
- let sizeInfo = "";
82
- try {
83
- const info = getWidgetBundleInfo(cwd, name);
84
- sizeInfo = ` — ${formatBytes(info.raw)}`;
85
- } catch {}
86
- return {
87
- value: name,
88
- label: `${manifest.name}${sizeInfo}`,
89
- };
90
- });
91
-
92
- const selected = await select({
93
- message: "Select widget to publish:",
94
- options: widgetOptions,
95
- });
96
-
97
- if (isCancel(selected)) {
98
- cancel("Publish cancelled.");
99
- process.exit(0);
97
+
98
+ let widgetName: string;
99
+ if (options?.name) {
100
+ if (!widgets.includes(options.name)) {
101
+ log.error(`Widget "${options.name}" not found. Available: ${widgets.join(", ")}`);
102
+ process.exit(1);
103
+ }
104
+ widgetName = options.name;
105
+ } else {
106
+ const widgetOptions = widgets.map((name) => {
107
+ const manifest = readManifest(cwd, name);
108
+ let sizeInfo = "";
109
+ try {
110
+ const info = getWidgetBundleInfo(cwd, name);
111
+ sizeInfo = ` — ${formatBytes(info.raw)}`;
112
+ } catch {}
113
+ return {
114
+ value: name,
115
+ label: `${manifest.name}${sizeInfo}`,
116
+ };
117
+ });
118
+
119
+ const selected = await select({
120
+ message: "Select widget to publish:",
121
+ options: widgetOptions,
122
+ });
123
+
124
+ if (isCancel(selected)) {
125
+ cancel("Publish cancelled.");
126
+ process.exit(0);
127
+ }
128
+ widgetName = selected as string;
100
129
  }
101
130
 
102
- const widgetName = selected as string;
103
131
  const manifest = readManifest(cwd, widgetName);
104
132
 
105
133
  // Step 5: Version bump (per-widget, from manifest)
106
134
  const currentVersion = manifest.version ?? "0.0.0";
107
135
 
108
- const bump = await select({
109
- message: `${manifest.name} version: ${currentVersion}. Bump?`,
110
- options: [
111
- { value: "keep", label: `Keep ${currentVersion}`, hint: "fails if already published" },
112
- { value: "patch", label: `Patch (${semver.inc(currentVersion, "patch")})` },
113
- { value: "minor", label: `Minor (${semver.inc(currentVersion, "minor")})` },
114
- { value: "major", label: `Major (${semver.inc(currentVersion, "major")})` },
115
- ],
116
- });
117
-
118
- if (isCancel(bump)) {
119
- cancel("Publish cancelled.");
120
- process.exit(0);
136
+ let bump: string;
137
+ if (options?.bump) {
138
+ bump = options.bump;
139
+ log.info(`Version: ${currentVersion} → ${bump === "keep" ? currentVersion : semver.inc(currentVersion, bump as semver.ReleaseType) ?? currentVersion}`);
140
+ } else {
141
+ const choice = await select({
142
+ message: `${manifest.name} version: ${currentVersion}. Bump?`,
143
+ options: [
144
+ { value: "keep", label: `Keep ${currentVersion}`, hint: "fails if already published" },
145
+ { value: "patch", label: `Patch (${semver.inc(currentVersion, "patch")})` },
146
+ { value: "minor", label: `Minor (${semver.inc(currentVersion, "minor")})` },
147
+ { value: "major", label: `Major (${semver.inc(currentVersion, "major")})` },
148
+ ],
149
+ });
150
+
151
+ if (isCancel(choice)) {
152
+ cancel("Publish cancelled.");
153
+ process.exit(0);
154
+ }
155
+ bump = choice as string;
121
156
  }
122
157
 
123
158
  let version = currentVersion;
@@ -35,7 +35,7 @@ This creates `src/{widget-name}/index.tsx` and `src/{widget-name}/manifest.json`
35
35
  Connect your widgets to a running GlassHome instance:
36
36
 
37
37
  ```bash
38
- bun widget connect http://<dashboard-api-host>:3333
38
+ bun widget connect http://homeassistant.local:3123
39
39
  ```
40
40
 
41
41
  This builds all widgets, serves them on your LAN IP, registers them with the dashboard, and watches for file changes. Widgets hot-reload as you edit.