openhome-cli 0.1.14 → 0.1.16

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/dist/cli.js CHANGED
@@ -878,18 +878,85 @@ async function deployCommand(pathArg, opts = {}) {
878
878
  });
879
879
  handleCancel(mode);
880
880
  if (mode === "zip") {
881
- const zipInput = await p.text({
882
- message: "Path to your zip file",
883
- placeholder: "./my-ability.zip",
884
- validate: (val) => {
885
- if (!val || !val.trim()) return "Path is required";
886
- const resolved = resolve(val.trim());
887
- if (!existsSync2(resolved)) return `File not found: ${val.trim()}`;
888
- if (!resolved.endsWith(".zip")) return "Must be a .zip file";
881
+ let scanForZips2 = function(dir, depth = 0) {
882
+ if (!existsSync2(dir)) return;
883
+ try {
884
+ const entries = readdirSync2(dir, { withFileTypes: true });
885
+ for (const entry of entries) {
886
+ const full = join2(dir, entry.name);
887
+ if (entry.isFile() && entry.name.endsWith(".zip") && !seen.has(full)) {
888
+ seen.add(full);
889
+ const shortDir = dir.startsWith(home) ? `~${dir.slice(home.length)}` : dir;
890
+ foundZips.push({
891
+ path: full,
892
+ label: `${entry.name} (${shortDir})`
893
+ });
894
+ } else if (entry.isDirectory() && depth < 2 && !entry.name.startsWith(".")) {
895
+ scanForZips2(full, depth + 1);
896
+ }
897
+ }
898
+ } catch {
889
899
  }
890
- });
891
- handleCancel(zipInput);
892
- await deployZip(resolve(zipInput.trim()), opts);
900
+ };
901
+ var scanForZips = scanForZips2;
902
+ const home = homedir();
903
+ const scanDirs = [
904
+ process.cwd(),
905
+ join2(home, "Desktop"),
906
+ join2(home, "Downloads"),
907
+ join2(home, "Documents")
908
+ ];
909
+ const foundZips = [];
910
+ const seen = /* @__PURE__ */ new Set();
911
+ for (const dir of scanDirs) {
912
+ scanForZips2(dir);
913
+ }
914
+ let zipPath;
915
+ if (foundZips.length > 0) {
916
+ const zipOptions = [
917
+ ...foundZips.map((z) => ({ value: z.path, label: z.label })),
918
+ {
919
+ value: "__custom__",
920
+ label: "Other...",
921
+ hint: "Enter a path manually"
922
+ }
923
+ ];
924
+ const selected = await p.select({
925
+ message: "Select your zip file",
926
+ options: zipOptions
927
+ });
928
+ handleCancel(selected);
929
+ if (selected === "__custom__") {
930
+ const zipInput = await p.text({
931
+ message: "Path to your zip file",
932
+ placeholder: "~/path/to/ability.zip",
933
+ validate: (val) => {
934
+ if (!val || !val.trim()) return "Path is required";
935
+ if (!existsSync2(resolve(val.trim())))
936
+ return `File not found: ${val.trim()}`;
937
+ if (!val.trim().endsWith(".zip")) return "Must be a .zip file";
938
+ }
939
+ });
940
+ handleCancel(zipInput);
941
+ zipPath = resolve(zipInput.trim());
942
+ } else {
943
+ zipPath = selected;
944
+ }
945
+ } else {
946
+ const zipInput = await p.text({
947
+ message: "Path to your zip file",
948
+ placeholder: "~/Downloads/my-ability.zip",
949
+ validate: (val) => {
950
+ if (!val || !val.trim()) return "Path is required";
951
+ if (!existsSync2(resolve(val.trim())))
952
+ return `File not found: ${val.trim()}`;
953
+ if (!val.trim().endsWith(".zip")) return "Must be a .zip file";
954
+ }
955
+ });
956
+ handleCancel(zipInput);
957
+ zipPath = resolve(zipInput.trim());
958
+ }
959
+ await deployZip(zipPath, opts);
893
960
  return;
894
961
  }
895
962
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openhome-cli",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "CLI for managing OpenHome voice AI abilities",
5
5
  "type": "module",
6
6
  "bin": {
@@ -148,18 +148,102 @@ export async function deployCommand(
148
148
  handleCancel(mode);
149
149
 
150
150
  if (mode === "zip") {
151
- const zipInput = await p.text({
152
- message: "Path to your zip file",
153
- placeholder: "./my-ability.zip",
154
- validate: (val) => {
155
- if (!val || !val.trim()) return "Path is required";
156
- const resolved = resolve(val.trim());
157
- if (!existsSync(resolved)) return `File not found: ${val.trim()}`;
158
- if (!resolved.endsWith(".zip")) return "Must be a .zip file";
159
- },
160
- });
161
- handleCancel(zipInput);
162
- await deployZip(resolve((zipInput as string).trim()), opts);
151
+ const home = homedir();
152
+ const scanDirs = [
153
+ process.cwd(),
154
+ join(home, "Desktop"),
155
+ join(home, "Downloads"),
156
+ join(home, "Documents"),
157
+ ];
158
+
159
+ const foundZips: { path: string; label: string }[] = [];
160
+ const seen = new Set<string>();
161
+
162
+ function scanForZips(dir: string, depth = 0): void {
163
+ if (!existsSync(dir)) return;
164
+ try {
165
+ const entries = readdirSync(dir, { withFileTypes: true });
166
+ for (const entry of entries) {
167
+ const full = join(dir, entry.name);
168
+ if (
169
+ entry.isFile() &&
170
+ entry.name.endsWith(".zip") &&
171
+ !seen.has(full)
172
+ ) {
173
+ seen.add(full);
174
+ const shortDir = dir.startsWith(home)
175
+ ? `~${dir.slice(home.length)}`
176
+ : dir;
177
+ foundZips.push({
178
+ path: full,
179
+ label: `${entry.name} (${shortDir})`,
180
+ });
181
+ } else if (
182
+ entry.isDirectory() &&
183
+ depth < 2 &&
184
+ !entry.name.startsWith(".")
185
+ ) {
186
+ scanForZips(full, depth + 1);
187
+ }
188
+ }
189
+ } catch {
190
+ // skip unreadable dirs
191
+ }
192
+ }
193
+
194
+ for (const dir of scanDirs) {
195
+ scanForZips(dir);
196
+ }
197
+
198
+ let zipPath: string;
199
+
200
+ if (foundZips.length > 0) {
201
+ const zipOptions = [
202
+ ...foundZips.map((z) => ({ value: z.path, label: z.label })),
203
+ {
204
+ value: "__custom__",
205
+ label: "Other...",
206
+ hint: "Enter a path manually",
207
+ },
208
+ ];
209
+ const selected = await p.select({
210
+ message: "Select your zip file",
211
+ options: zipOptions,
212
+ });
213
+ handleCancel(selected);
214
+
215
+ if (selected === "__custom__") {
216
+ const zipInput = await p.text({
217
+ message: "Path to your zip file",
218
+ placeholder: "~/path/to/ability.zip",
219
+ validate: (val) => {
220
+ if (!val || !val.trim()) return "Path is required";
221
+ if (!existsSync(resolve(val.trim())))
222
+ return `File not found: ${val.trim()}`;
223
+ if (!val.trim().endsWith(".zip")) return "Must be a .zip file";
224
+ },
225
+ });
226
+ handleCancel(zipInput);
227
+ zipPath = resolve((zipInput as string).trim());
228
+ } else {
229
+ zipPath = selected as string;
230
+ }
231
+ } else {
232
+ const zipInput = await p.text({
233
+ message: "Path to your zip file",
234
+ placeholder: "~/Downloads/my-ability.zip",
235
+ validate: (val) => {
236
+ if (!val || !val.trim()) return "Path is required";
237
+ if (!existsSync(resolve(val.trim())))
238
+ return `File not found: ${val.trim()}`;
239
+ if (!val.trim().endsWith(".zip")) return "Must be a .zip file";
240
+ },
241
+ });
242
+ handleCancel(zipInput);
243
+ zipPath = resolve((zipInput as string).trim());
244
+ }
245
+
246
+ await deployZip(zipPath, opts);
163
247
  return;
164
248
  }
165
249
  }