@feralfile/cli 2.1.0 → 2.2.0
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/package.json +1 -1
- package/dist/src/commands/device.js +45 -0
- package/dist/src/utilities/device-rename.js +50 -0
- package/docs/CONFIGURATION.md +1 -0
- package/docs/EXAMPLES.md +3 -0
- package/docs/README.md +4 -0
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -11,6 +11,7 @@ const device_lookup_1 = require("../utilities/device-lookup");
|
|
|
11
11
|
const device_normalize_1 = require("../utilities/device-normalize");
|
|
12
12
|
const device_upsert_1 = require("../utilities/device-upsert");
|
|
13
13
|
const device_default_1 = require("../utilities/device-default");
|
|
14
|
+
const device_rename_1 = require("../utilities/device-rename");
|
|
14
15
|
const config_files_1 = require("./helpers/config-files");
|
|
15
16
|
const device_discovery_1 = require("./helpers/device-discovery");
|
|
16
17
|
const prompt_1 = require("./helpers/prompt");
|
|
@@ -291,6 +292,50 @@ deviceCommand
|
|
|
291
292
|
process.exit(1);
|
|
292
293
|
}
|
|
293
294
|
});
|
|
295
|
+
deviceCommand
|
|
296
|
+
.command('rename')
|
|
297
|
+
.description('Rename a configured FF1 device (host, API key, and default status are untouched)')
|
|
298
|
+
.argument('<name>', 'Current device name or host')
|
|
299
|
+
.argument('<new-name>', 'New device name')
|
|
300
|
+
.action(async (name, newName) => {
|
|
301
|
+
try {
|
|
302
|
+
const configPath = await (0, config_files_1.resolveExistingConfigPath)();
|
|
303
|
+
if (!configPath) {
|
|
304
|
+
console.log(chalk_1.default.red('config.json not found'));
|
|
305
|
+
console.log(chalk_1.default.dim('Run: ff-cli setup'));
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
const config = await (0, config_files_1.readConfigFile)(configPath);
|
|
309
|
+
const existingDevices = config.ff1Devices?.devices || [];
|
|
310
|
+
if (existingDevices.length === 0) {
|
|
311
|
+
console.log(chalk_1.default.yellow('\nNo devices configured'));
|
|
312
|
+
console.log(chalk_1.default.dim('Run: ff-cli device add\n'));
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
315
|
+
let result;
|
|
316
|
+
try {
|
|
317
|
+
result = (0, device_rename_1.renameDevice)(existingDevices, name, newName);
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
console.error(chalk_1.default.red(`\n${error.message}`));
|
|
321
|
+
const names = existingDevices.map((d) => d.name || d.host).join(', ');
|
|
322
|
+
console.log(chalk_1.default.dim(`Available devices: ${names}\n`));
|
|
323
|
+
process.exit(1);
|
|
324
|
+
}
|
|
325
|
+
if (result.unchanged) {
|
|
326
|
+
console.log(chalk_1.default.dim(`\n"${result.renamed.name}" is already named that.\n`));
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
config.ff1Devices = { devices: result.devices };
|
|
330
|
+
await fs_1.promises.writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf-8');
|
|
331
|
+
const from = result.previousName || result.renamed.host;
|
|
332
|
+
console.log(chalk_1.default.green(`\nRenamed device: ${from} → ${result.renamed.name}\n`));
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
console.error(chalk_1.default.red('\nError:'), error.message);
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
294
339
|
deviceCommand
|
|
295
340
|
.command('default')
|
|
296
341
|
.description('Set the default FF1 device (reorders so this device is used when -d is omitted)')
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renameDevice = renameDevice;
|
|
4
|
+
const device_normalize_1 = require("./device-normalize");
|
|
5
|
+
/**
|
|
6
|
+
* Rename a configured device without touching host, apiKey, topicID, or list
|
|
7
|
+
* position — a pure config edit that needs no discovery or network access
|
|
8
|
+
* (unlike `device add`, whose update path requires the host or mDNS).
|
|
9
|
+
*
|
|
10
|
+
* Matches by name (case-insensitive) or by host URL, mirroring `device remove`
|
|
11
|
+
* so unnamed legacy entries can still be targeted (renaming gives them a name
|
|
12
|
+
* for the first time).
|
|
13
|
+
*
|
|
14
|
+
* @throws {Error} When no device matches the identifier, the new name is
|
|
15
|
+
* empty, or the new name is already used by a different device
|
|
16
|
+
* (case-insensitive, so lookups elsewhere stay unambiguous).
|
|
17
|
+
*/
|
|
18
|
+
function renameDevice(devices, identifier, newName) {
|
|
19
|
+
const trimmedName = newName.trim();
|
|
20
|
+
if (!trimmedName) {
|
|
21
|
+
throw new Error('New device name must not be empty');
|
|
22
|
+
}
|
|
23
|
+
const normalizedArg = identifier.toLowerCase();
|
|
24
|
+
let normalizedArgHost = '';
|
|
25
|
+
try {
|
|
26
|
+
normalizedArgHost = (0, device_normalize_1.normalizeDeviceHost)(identifier).toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// not a valid URL — host matching will not apply
|
|
30
|
+
}
|
|
31
|
+
const index = devices.findIndex((d) => (d.name && d.name.toLowerCase() === normalizedArg) ||
|
|
32
|
+
(d.host && d.host.toLowerCase() === normalizedArg) ||
|
|
33
|
+
(normalizedArgHost &&
|
|
34
|
+
d.host &&
|
|
35
|
+
(0, device_normalize_1.normalizeDeviceHost)(d.host).toLowerCase() === normalizedArgHost));
|
|
36
|
+
if (index === -1) {
|
|
37
|
+
throw new Error(`Device "${identifier}" not found`);
|
|
38
|
+
}
|
|
39
|
+
const conflict = devices.find((d, i) => i !== index && d.name && d.name.toLowerCase() === trimmedName.toLowerCase());
|
|
40
|
+
if (conflict) {
|
|
41
|
+
throw new Error(`Device name "${trimmedName}" is already used by another device (${conflict.host})`);
|
|
42
|
+
}
|
|
43
|
+
const target = devices[index];
|
|
44
|
+
if (target.name === trimmedName) {
|
|
45
|
+
return { devices: [...devices], renamed: target, previousName: target.name, unchanged: true };
|
|
46
|
+
}
|
|
47
|
+
const updated = [...devices];
|
|
48
|
+
updated[index] = { ...target, name: trimmedName };
|
|
49
|
+
return { devices: updated, renamed: updated[index], previousName: target.name, unchanged: false };
|
|
50
|
+
}
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -139,6 +139,7 @@ You can also manage devices independently with:
|
|
|
139
139
|
non-interactively with `--host`, `--name`, and the physical `--id` shown in
|
|
140
140
|
Feral File mobile. Manual devices need the ID before relayer pairing.
|
|
141
141
|
- `ff-cli device list` – Show all configured devices.
|
|
142
|
+
- `ff-cli device rename <name> <new-name>` – Rename a device without touching its host, API key, or default status. Works offline; also accepts the host URL as the identifier, so unnamed legacy entries can be given a name.
|
|
142
143
|
- `ff-cli device remove <name>` – Remove a device by name.
|
|
143
144
|
- `ff-cli device default <name>` – Promote a device to the top of the list so it is used when `-d` is omitted.
|
|
144
145
|
- `ff-cli device pair [name]` – Display a one-time handoff code and key-bound
|
package/docs/EXAMPLES.md
CHANGED
|
@@ -385,6 +385,9 @@ npm run dev -- device add
|
|
|
385
385
|
# Add a device non-interactively
|
|
386
386
|
npm run dev -- device add --host 192.168.1.100 --name kitchen
|
|
387
387
|
|
|
388
|
+
# Rename a device (host, API key, and default status are untouched)
|
|
389
|
+
npm run dev -- device rename kitchen gallery
|
|
390
|
+
|
|
388
391
|
# Remove a device by name
|
|
389
392
|
npm run dev -- device remove kitchen
|
|
390
393
|
|
package/docs/README.md
CHANGED
|
@@ -120,6 +120,7 @@ Both paths run the same deterministic pipeline: fetch metadata, assemble a DP-1
|
|
|
120
120
|
- `device add` – Add a device with mDNS or manual `--host`, `--name`, and `--id`
|
|
121
121
|
- Options: `--host <host>`, `--name <name>`, `--id <id>`
|
|
122
122
|
- `device pair [name]` – Securely receive relayer access from Feral File mobile
|
|
123
|
+
- `device rename <name> <new-name>` – Rename a configured FF1 device (host, API key, and default status are untouched)
|
|
123
124
|
- `device remove <name>` – Remove a configured FF1 device
|
|
124
125
|
- `device default <name>` – Set the default FF1 device (used when `-d` is omitted)
|
|
125
126
|
- `config <init|show|validate>` – Manage configuration
|
|
@@ -274,6 +275,9 @@ ff-cli device add
|
|
|
274
275
|
# Add a device non-interactively
|
|
275
276
|
ff-cli device add --host 192.168.1.100 --name kitchen --id FF1-XXXXXXXX
|
|
276
277
|
|
|
278
|
+
# Rename a device (host, API key, and default status are untouched)
|
|
279
|
+
ff-cli device rename kitchen gallery
|
|
280
|
+
|
|
277
281
|
# Remove a device by name
|
|
278
282
|
ff-cli device remove kitchen
|
|
279
283
|
|