simvyn 2.0.0 → 2.1.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/dashboard/assets/{index-Pv0mHRGr.css → index-B6SC-KfX.css} +44 -2
- package/dist/dashboard/assets/{index-SgS9nwZ7.js → index-jHtyqXZH.js} +185 -13
- package/dist/dashboard/assets/index-jHtyqXZH.js.map +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/index.js +153 -44
- package/package.json +1 -1
- package/dist/dashboard/assets/index-SgS9nwZ7.js.map +0 -1
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
}
|
|
39
39
|
</style>
|
|
40
40
|
<title>simvyn</title>
|
|
41
|
-
<script type="module" crossorigin src="/assets/index-
|
|
42
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
41
|
+
<script type="module" crossorigin src="/assets/index-jHtyqXZH.js"></script>
|
|
42
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B6SC-KfX.css">
|
|
43
43
|
</head>
|
|
44
44
|
<body>
|
|
45
45
|
<div id="root"></div>
|
package/dist/index.js
CHANGED
|
@@ -1488,9 +1488,64 @@ var init_storage = __esm({
|
|
|
1488
1488
|
}
|
|
1489
1489
|
});
|
|
1490
1490
|
|
|
1491
|
+
// ../core/src/favourites.ts
|
|
1492
|
+
async function getFavourites() {
|
|
1493
|
+
return await storage.read(KEY) ?? [];
|
|
1494
|
+
}
|
|
1495
|
+
async function addFavourite(id) {
|
|
1496
|
+
const favs = await getFavourites();
|
|
1497
|
+
if (favs.includes(id)) return;
|
|
1498
|
+
favs.push(id);
|
|
1499
|
+
favs.sort();
|
|
1500
|
+
await storage.write(KEY, favs);
|
|
1501
|
+
}
|
|
1502
|
+
async function removeFavourite(id) {
|
|
1503
|
+
const favs = await getFavourites();
|
|
1504
|
+
const idx = favs.indexOf(id);
|
|
1505
|
+
if (idx === -1) return;
|
|
1506
|
+
favs.splice(idx, 1);
|
|
1507
|
+
await storage.write(KEY, favs);
|
|
1508
|
+
}
|
|
1509
|
+
async function cleanupStaleFavourites(currentDeviceIds, missCountMap, threshold = 3) {
|
|
1510
|
+
const favs = await getFavourites();
|
|
1511
|
+
const currentSet = new Set(currentDeviceIds);
|
|
1512
|
+
const toRemove = [];
|
|
1513
|
+
for (const id of favs) {
|
|
1514
|
+
if (currentSet.has(id)) {
|
|
1515
|
+
missCountMap.delete(id);
|
|
1516
|
+
} else {
|
|
1517
|
+
const count = (missCountMap.get(id) ?? 0) + 1;
|
|
1518
|
+
missCountMap.set(id, count);
|
|
1519
|
+
if (count > threshold) {
|
|
1520
|
+
toRemove.push(id);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
if (toRemove.length > 0) {
|
|
1525
|
+
const cleaned = favs.filter((id) => !toRemove.includes(id));
|
|
1526
|
+
await storage.write(KEY, cleaned);
|
|
1527
|
+
for (const id of toRemove) {
|
|
1528
|
+
missCountMap.delete(id);
|
|
1529
|
+
}
|
|
1530
|
+
return cleaned;
|
|
1531
|
+
}
|
|
1532
|
+
return favs;
|
|
1533
|
+
}
|
|
1534
|
+
var storage, KEY;
|
|
1535
|
+
var init_favourites = __esm({
|
|
1536
|
+
"../core/src/favourites.ts"() {
|
|
1537
|
+
"use strict";
|
|
1538
|
+
init_storage();
|
|
1539
|
+
storage = createModuleStorage("favourites");
|
|
1540
|
+
KEY = "favourites";
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
|
|
1491
1544
|
// ../core/src/index.ts
|
|
1492
1545
|
var src_exports = {};
|
|
1493
1546
|
__export(src_exports, {
|
|
1547
|
+
addFavourite: () => addFavourite,
|
|
1548
|
+
cleanupStaleFavourites: () => cleanupStaleFavourites,
|
|
1494
1549
|
createAndroidAdapter: () => createAndroidAdapter,
|
|
1495
1550
|
createAvailableAdapters: () => createAvailableAdapters,
|
|
1496
1551
|
createDeviceManager: () => createDeviceManager,
|
|
@@ -1498,12 +1553,14 @@ __export(src_exports, {
|
|
|
1498
1553
|
createModuleStorage: () => createModuleStorage,
|
|
1499
1554
|
createProcessManager: () => createProcessManager,
|
|
1500
1555
|
getDevicectlStatus: () => getDevicectlStatus,
|
|
1556
|
+
getFavourites: () => getFavourites,
|
|
1501
1557
|
getSimvynDir: () => getSimvynDir,
|
|
1502
1558
|
hasBinary: () => hasBinary,
|
|
1503
1559
|
isAndroidPhysical: () => isAndroidPhysical,
|
|
1504
1560
|
isLinux: () => isLinux,
|
|
1505
1561
|
isMacOS: () => isMacOS,
|
|
1506
1562
|
isPhysicalDevice: () => isPhysicalDevice,
|
|
1563
|
+
removeFavourite: () => removeFavourite,
|
|
1507
1564
|
setVerbose: () => setVerbose,
|
|
1508
1565
|
stripPhysicalPrefix: () => stripPhysicalPrefix,
|
|
1509
1566
|
verboseExec: () => verboseExec,
|
|
@@ -1517,6 +1574,7 @@ var init_src = __esm({
|
|
|
1517
1574
|
init_platform();
|
|
1518
1575
|
init_process_manager();
|
|
1519
1576
|
init_storage();
|
|
1577
|
+
init_favourites();
|
|
1520
1578
|
init_verbose_exec();
|
|
1521
1579
|
}
|
|
1522
1580
|
});
|
|
@@ -3685,16 +3743,16 @@ function getStarterCollections() {
|
|
|
3685
3743
|
// ../modules/collections/routes.ts
|
|
3686
3744
|
var activeRuns = /* @__PURE__ */ new Map();
|
|
3687
3745
|
async function collectionsRoutes(fastify) {
|
|
3688
|
-
const
|
|
3746
|
+
const storage4 = createModuleStorage("collections");
|
|
3689
3747
|
async function readCollections() {
|
|
3690
|
-
const stored = await
|
|
3748
|
+
const stored = await storage4.read("collections");
|
|
3691
3749
|
if (stored && stored.length > 0) return stored;
|
|
3692
3750
|
const starters = getStarterCollections();
|
|
3693
3751
|
await writeCollections(starters);
|
|
3694
3752
|
return starters;
|
|
3695
3753
|
}
|
|
3696
3754
|
async function writeCollections(collections) {
|
|
3697
|
-
await
|
|
3755
|
+
await storage4.write("collections", collections);
|
|
3698
3756
|
}
|
|
3699
3757
|
fastify.get("/actions", async () => {
|
|
3700
3758
|
const descriptors = getActionDescriptors();
|
|
@@ -3859,8 +3917,8 @@ var collectionsModule = {
|
|
|
3859
3917
|
const cmd = program2.command("collections").description("Manage device action collections");
|
|
3860
3918
|
cmd.command("list").description("List all saved collections").action(async () => {
|
|
3861
3919
|
const { createModuleStorage: createModuleStorage2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
3862
|
-
const
|
|
3863
|
-
const collections = await
|
|
3920
|
+
const storage4 = createModuleStorage2("collections");
|
|
3921
|
+
const collections = await storage4.read(
|
|
3864
3922
|
"collections"
|
|
3865
3923
|
) ?? [];
|
|
3866
3924
|
if (collections.length === 0) {
|
|
@@ -3877,8 +3935,8 @@ var collectionsModule = {
|
|
|
3877
3935
|
});
|
|
3878
3936
|
cmd.command("show <id>").description("Show a collection's details").action(async (id) => {
|
|
3879
3937
|
const { createModuleStorage: createModuleStorage2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
3880
|
-
const
|
|
3881
|
-
const collections = await
|
|
3938
|
+
const storage4 = createModuleStorage2("collections");
|
|
3939
|
+
const collections = await storage4.read("collections") ?? [];
|
|
3882
3940
|
const collection = collections.find((c) => c.id.startsWith(id));
|
|
3883
3941
|
if (!collection) {
|
|
3884
3942
|
console.error(`Collection not found: ${id}`);
|
|
@@ -3896,8 +3954,8 @@ var collectionsModule = {
|
|
|
3896
3954
|
});
|
|
3897
3955
|
cmd.command("create <name>").description("Create a new empty collection").option("-d, --description <desc>", "Collection description").action(async (name, opts) => {
|
|
3898
3956
|
const { createModuleStorage: createModuleStorage2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
3899
|
-
const
|
|
3900
|
-
const collections = await
|
|
3957
|
+
const storage4 = createModuleStorage2("collections");
|
|
3958
|
+
const collections = await storage4.read("collections") ?? [];
|
|
3901
3959
|
const collection = {
|
|
3902
3960
|
id: crypto.randomUUID(),
|
|
3903
3961
|
name,
|
|
@@ -3908,13 +3966,13 @@ var collectionsModule = {
|
|
|
3908
3966
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3909
3967
|
};
|
|
3910
3968
|
collections.push(collection);
|
|
3911
|
-
await
|
|
3969
|
+
await storage4.write("collections", collections);
|
|
3912
3970
|
console.log(`Created collection: ${collection.id}`);
|
|
3913
3971
|
});
|
|
3914
3972
|
cmd.command("delete <id>").description("Delete a collection").action(async (id) => {
|
|
3915
3973
|
const { createModuleStorage: createModuleStorage2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
3916
|
-
const
|
|
3917
|
-
const collections = await
|
|
3974
|
+
const storage4 = createModuleStorage2("collections");
|
|
3975
|
+
const collections = await storage4.read("collections") ?? [];
|
|
3918
3976
|
const idx = collections.findIndex((c) => c.id.startsWith(id));
|
|
3919
3977
|
if (idx === -1) {
|
|
3920
3978
|
console.error(`Collection not found: ${id}`);
|
|
@@ -3922,13 +3980,13 @@ var collectionsModule = {
|
|
|
3922
3980
|
}
|
|
3923
3981
|
const removed = collections[idx];
|
|
3924
3982
|
collections.splice(idx, 1);
|
|
3925
|
-
await
|
|
3983
|
+
await storage4.write("collections", collections);
|
|
3926
3984
|
console.log(`Deleted collection: ${removed.name}`);
|
|
3927
3985
|
});
|
|
3928
3986
|
cmd.command("duplicate <id>").description("Duplicate a collection").option("-n, --name <newName>", "Name for the duplicate").action(async (id, opts) => {
|
|
3929
3987
|
const { createModuleStorage: createModuleStorage2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
3930
|
-
const
|
|
3931
|
-
const collections = await
|
|
3988
|
+
const storage4 = createModuleStorage2("collections");
|
|
3989
|
+
const collections = await storage4.read("collections") ?? [];
|
|
3932
3990
|
const original = collections.find((c) => c.id.startsWith(id));
|
|
3933
3991
|
if (!original) {
|
|
3934
3992
|
console.error(`Collection not found: ${id}`);
|
|
@@ -3944,19 +4002,19 @@ var collectionsModule = {
|
|
|
3944
4002
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3945
4003
|
};
|
|
3946
4004
|
collections.push(duplicate);
|
|
3947
|
-
await
|
|
4005
|
+
await storage4.write("collections", collections);
|
|
3948
4006
|
console.log(`Duplicated collection: ${duplicate.id}`);
|
|
3949
4007
|
});
|
|
3950
4008
|
cmd.command("apply <name-or-id>").description("Execute a collection on one or more devices").argument("<devices...>", "Device IDs to execute on").action(async (nameOrId, devices) => {
|
|
3951
4009
|
const { createAvailableAdapters: createAvailableAdapters2, createDeviceManager: createDeviceManager2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
3952
4010
|
const { createModuleStorage: createModuleStorage2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
3953
4011
|
const { runCollection: runCollection2 } = await Promise.resolve().then(() => (init_execution_engine(), execution_engine_exports));
|
|
3954
|
-
const
|
|
4012
|
+
const storage4 = createModuleStorage2("collections");
|
|
3955
4013
|
const adapters = await createAvailableAdapters2();
|
|
3956
4014
|
const dm = createDeviceManager2(adapters);
|
|
3957
4015
|
try {
|
|
3958
4016
|
await dm.refresh();
|
|
3959
|
-
const collections = await
|
|
4017
|
+
const collections = await storage4.read("collections") ?? [];
|
|
3960
4018
|
const collection = collections.find(
|
|
3961
4019
|
(c) => c.id.startsWith(nameOrId) || c.name.toLowerCase() === nameOrId.toLowerCase()
|
|
3962
4020
|
);
|
|
@@ -4716,7 +4774,7 @@ init_src();
|
|
|
4716
4774
|
import { randomUUID } from "crypto";
|
|
4717
4775
|
var MAX_HISTORY = 50;
|
|
4718
4776
|
async function deepLinkRoutes(fastify) {
|
|
4719
|
-
const
|
|
4777
|
+
const storage4 = createModuleStorage("deep-links");
|
|
4720
4778
|
fastify.post("/open", async (req, reply) => {
|
|
4721
4779
|
const { deviceId, url } = req.body;
|
|
4722
4780
|
const device = fastify.deviceManager.devices.find((d) => d.id === deviceId);
|
|
@@ -4728,7 +4786,7 @@ async function deepLinkRoutes(fastify) {
|
|
|
4728
4786
|
return reply.status(400).send({ error: "Deep links not supported for this platform" });
|
|
4729
4787
|
try {
|
|
4730
4788
|
await adapter.openUrl(device.id, url);
|
|
4731
|
-
const history = await
|
|
4789
|
+
const history = await storage4.read("history") ?? [];
|
|
4732
4790
|
history.unshift({
|
|
4733
4791
|
url,
|
|
4734
4792
|
deviceId: device.id,
|
|
@@ -4736,21 +4794,21 @@ async function deepLinkRoutes(fastify) {
|
|
|
4736
4794
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4737
4795
|
});
|
|
4738
4796
|
if (history.length > MAX_HISTORY) history.length = MAX_HISTORY;
|
|
4739
|
-
await
|
|
4797
|
+
await storage4.write("history", history);
|
|
4740
4798
|
return { success: true, url, deviceId: device.id };
|
|
4741
4799
|
} catch (err) {
|
|
4742
4800
|
return reply.status(500).send({ error: err.message });
|
|
4743
4801
|
}
|
|
4744
4802
|
});
|
|
4745
4803
|
fastify.get("/favorites", async () => {
|
|
4746
|
-
const favorites = await
|
|
4804
|
+
const favorites = await storage4.read("favorites") ?? [];
|
|
4747
4805
|
return { favorites };
|
|
4748
4806
|
});
|
|
4749
4807
|
fastify.post(
|
|
4750
4808
|
"/favorites",
|
|
4751
4809
|
async (req) => {
|
|
4752
4810
|
const { url, label, bundleId } = req.body;
|
|
4753
|
-
const favorites = await
|
|
4811
|
+
const favorites = await storage4.read("favorites") ?? [];
|
|
4754
4812
|
const favorite = {
|
|
4755
4813
|
id: randomUUID(),
|
|
4756
4814
|
url,
|
|
@@ -4759,21 +4817,21 @@ async function deepLinkRoutes(fastify) {
|
|
|
4759
4817
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4760
4818
|
};
|
|
4761
4819
|
favorites.push(favorite);
|
|
4762
|
-
await
|
|
4820
|
+
await storage4.write("favorites", favorites);
|
|
4763
4821
|
return favorite;
|
|
4764
4822
|
}
|
|
4765
4823
|
);
|
|
4766
4824
|
fastify.delete("/favorites/:id", async (req, reply) => {
|
|
4767
4825
|
const { id } = req.params;
|
|
4768
|
-
const favorites = await
|
|
4826
|
+
const favorites = await storage4.read("favorites") ?? [];
|
|
4769
4827
|
const idx = favorites.findIndex((f) => f.id === id);
|
|
4770
4828
|
if (idx === -1) return reply.status(404).send({ error: "Favorite not found" });
|
|
4771
4829
|
favorites.splice(idx, 1);
|
|
4772
|
-
await
|
|
4830
|
+
await storage4.write("favorites", favorites);
|
|
4773
4831
|
return { success: true };
|
|
4774
4832
|
});
|
|
4775
4833
|
fastify.get("/history", async () => {
|
|
4776
|
-
const history = await
|
|
4834
|
+
const history = await storage4.read("history") ?? [];
|
|
4777
4835
|
return { history };
|
|
4778
4836
|
});
|
|
4779
4837
|
}
|
|
@@ -4820,6 +4878,7 @@ var deepLinksModule = {
|
|
|
4820
4878
|
var manifest_default6 = deepLinksModule;
|
|
4821
4879
|
|
|
4822
4880
|
// ../modules/device-management/routes.ts
|
|
4881
|
+
init_src();
|
|
4823
4882
|
async function deviceRoutes(fastify) {
|
|
4824
4883
|
fastify.get("/list", async () => {
|
|
4825
4884
|
return { devices: fastify.deviceManager.devices };
|
|
@@ -5040,6 +5099,17 @@ async function deviceRoutes(fastify) {
|
|
|
5040
5099
|
return reply.status(500).send({ error: err.message });
|
|
5041
5100
|
}
|
|
5042
5101
|
});
|
|
5102
|
+
fastify.get("/favourites", async () => {
|
|
5103
|
+
return { favourites: await getFavourites() };
|
|
5104
|
+
});
|
|
5105
|
+
fastify.post("/favourites", async (req) => {
|
|
5106
|
+
await addFavourite(req.body.deviceId);
|
|
5107
|
+
return { success: true };
|
|
5108
|
+
});
|
|
5109
|
+
fastify.delete("/favourites", async (req) => {
|
|
5110
|
+
await removeFavourite(req.body.deviceId);
|
|
5111
|
+
return { success: true };
|
|
5112
|
+
});
|
|
5043
5113
|
fastify.post("/refresh", async () => {
|
|
5044
5114
|
const devices = await fastify.deviceManager.refresh();
|
|
5045
5115
|
return { devices };
|
|
@@ -7807,7 +7877,7 @@ import { tmpdir as tmpdir7 } from "os";
|
|
|
7807
7877
|
import { join as join14 } from "path";
|
|
7808
7878
|
import { promisify as promisify9 } from "util";
|
|
7809
7879
|
var execFileAsync9 = promisify9(execFile9);
|
|
7810
|
-
var
|
|
7880
|
+
var storage2 = createModuleStorage("push");
|
|
7811
7881
|
async function pushRoutes(fastify) {
|
|
7812
7882
|
fastify.post(
|
|
7813
7883
|
"/send",
|
|
@@ -7828,7 +7898,7 @@ async function pushRoutes(fastify) {
|
|
|
7828
7898
|
try {
|
|
7829
7899
|
await writeFile4(tmpFile, JSON.stringify(payload), "utf-8");
|
|
7830
7900
|
await execFileAsync9("xcrun", ["simctl", "push", deviceId, bundleId, tmpFile]);
|
|
7831
|
-
const history = await
|
|
7901
|
+
const history = await storage2.read("history") ?? [];
|
|
7832
7902
|
history.unshift({
|
|
7833
7903
|
bundleId,
|
|
7834
7904
|
payload,
|
|
@@ -7837,7 +7907,7 @@ async function pushRoutes(fastify) {
|
|
|
7837
7907
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
7838
7908
|
});
|
|
7839
7909
|
if (history.length > 50) history.length = 50;
|
|
7840
|
-
await
|
|
7910
|
+
await storage2.write("history", history);
|
|
7841
7911
|
return { success: true };
|
|
7842
7912
|
} catch (err) {
|
|
7843
7913
|
return reply.status(500).send({ error: err.message });
|
|
@@ -7852,7 +7922,7 @@ async function pushRoutes(fastify) {
|
|
|
7852
7922
|
return { templates: pushTemplates2 };
|
|
7853
7923
|
});
|
|
7854
7924
|
fastify.get("/payloads", async () => {
|
|
7855
|
-
const payloads = await
|
|
7925
|
+
const payloads = await storage2.read("payloads") ?? [];
|
|
7856
7926
|
return { payloads };
|
|
7857
7927
|
});
|
|
7858
7928
|
fastify.post(
|
|
@@ -7862,7 +7932,7 @@ async function pushRoutes(fastify) {
|
|
|
7862
7932
|
if (!name || !payload) {
|
|
7863
7933
|
return reply.status(400).send({ error: "name and payload are required" });
|
|
7864
7934
|
}
|
|
7865
|
-
const payloads = await
|
|
7935
|
+
const payloads = await storage2.read("payloads") ?? [];
|
|
7866
7936
|
const created = {
|
|
7867
7937
|
id: randomUUID2(),
|
|
7868
7938
|
name,
|
|
@@ -7871,21 +7941,21 @@ async function pushRoutes(fastify) {
|
|
|
7871
7941
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7872
7942
|
};
|
|
7873
7943
|
payloads.push(created);
|
|
7874
|
-
await
|
|
7944
|
+
await storage2.write("payloads", payloads);
|
|
7875
7945
|
return created;
|
|
7876
7946
|
}
|
|
7877
7947
|
);
|
|
7878
7948
|
fastify.delete("/payloads/:id", async (req, reply) => {
|
|
7879
7949
|
const { id } = req.params;
|
|
7880
|
-
const payloads = await
|
|
7950
|
+
const payloads = await storage2.read("payloads") ?? [];
|
|
7881
7951
|
const idx = payloads.findIndex((p) => p.id === id);
|
|
7882
7952
|
if (idx === -1) return reply.status(404).send({ error: "Payload not found" });
|
|
7883
7953
|
payloads.splice(idx, 1);
|
|
7884
|
-
await
|
|
7954
|
+
await storage2.write("payloads", payloads);
|
|
7885
7955
|
return { success: true };
|
|
7886
7956
|
});
|
|
7887
7957
|
fastify.get("/history", async () => {
|
|
7888
|
-
const history = await
|
|
7958
|
+
const history = await storage2.read("history") ?? [];
|
|
7889
7959
|
return { history };
|
|
7890
7960
|
});
|
|
7891
7961
|
}
|
|
@@ -8011,7 +8081,7 @@ function getActiveRecordings() {
|
|
|
8011
8081
|
}
|
|
8012
8082
|
|
|
8013
8083
|
// ../modules/screenshot/routes.ts
|
|
8014
|
-
var
|
|
8084
|
+
var storage3 = createModuleStorage("screenshot");
|
|
8015
8085
|
var capturesDir = join15(getSimvynDir(), "screenshot", "captures");
|
|
8016
8086
|
var recordingsDir = join15(getSimvynDir(), "screenshot", "recordings");
|
|
8017
8087
|
async function ensureDirs() {
|
|
@@ -8019,9 +8089,9 @@ async function ensureDirs() {
|
|
|
8019
8089
|
await mkdir4(recordingsDir, { recursive: true });
|
|
8020
8090
|
}
|
|
8021
8091
|
async function appendHistory(entry) {
|
|
8022
|
-
const history = await
|
|
8092
|
+
const history = await storage3.read("history") ?? [];
|
|
8023
8093
|
history.push(entry);
|
|
8024
|
-
await
|
|
8094
|
+
await storage3.write("history", history);
|
|
8025
8095
|
}
|
|
8026
8096
|
async function screenshotRoutes(fastify) {
|
|
8027
8097
|
await ensureDirs();
|
|
@@ -8112,12 +8182,12 @@ async function screenshotRoutes(fastify) {
|
|
|
8112
8182
|
}
|
|
8113
8183
|
});
|
|
8114
8184
|
fastify.get("/history", async () => {
|
|
8115
|
-
const history = await
|
|
8185
|
+
const history = await storage3.read("history") ?? [];
|
|
8116
8186
|
return history;
|
|
8117
8187
|
});
|
|
8118
8188
|
fastify.delete("/history/:filename", async (req, reply) => {
|
|
8119
8189
|
const { filename } = req.params;
|
|
8120
|
-
const history = await
|
|
8190
|
+
const history = await storage3.read("history") ?? [];
|
|
8121
8191
|
const idx = history.findIndex((e) => e.filename === filename);
|
|
8122
8192
|
if (idx === -1) return reply.status(404).send({ error: "Entry not found" });
|
|
8123
8193
|
const entry = history[idx];
|
|
@@ -8126,11 +8196,11 @@ async function screenshotRoutes(fastify) {
|
|
|
8126
8196
|
} catch {
|
|
8127
8197
|
}
|
|
8128
8198
|
history.splice(idx, 1);
|
|
8129
|
-
await
|
|
8199
|
+
await storage3.write("history", history);
|
|
8130
8200
|
return { deleted: true };
|
|
8131
8201
|
});
|
|
8132
8202
|
fastify.delete("/history", async () => {
|
|
8133
|
-
const history = await
|
|
8203
|
+
const history = await storage3.read("history") ?? [];
|
|
8134
8204
|
const count = history.length;
|
|
8135
8205
|
for (const entry of history) {
|
|
8136
8206
|
try {
|
|
@@ -8138,7 +8208,7 @@ async function screenshotRoutes(fastify) {
|
|
|
8138
8208
|
} catch {
|
|
8139
8209
|
}
|
|
8140
8210
|
}
|
|
8141
|
-
await
|
|
8211
|
+
await storage3.write("history", []);
|
|
8142
8212
|
return { cleared: true, count };
|
|
8143
8213
|
});
|
|
8144
8214
|
fastify.get("/download/:filename", async (req, reply) => {
|
|
@@ -8482,6 +8552,45 @@ function registerDeviceCommand(program2) {
|
|
|
8482
8552
|
process.exit(1);
|
|
8483
8553
|
}
|
|
8484
8554
|
});
|
|
8555
|
+
device.command("favourite <id>").description("Add a device to favourites").action(async (id) => {
|
|
8556
|
+
try {
|
|
8557
|
+
const { device: dev } = await findDevice(id);
|
|
8558
|
+
await addFavourite(dev.id);
|
|
8559
|
+
console.log(`\u2713 Added ${dev.name} to favourites`);
|
|
8560
|
+
} catch (err) {
|
|
8561
|
+
console.error(`Failed to favourite device: ${err.message}`);
|
|
8562
|
+
process.exit(1);
|
|
8563
|
+
}
|
|
8564
|
+
});
|
|
8565
|
+
device.command("unfavourite <id>").description("Remove a device from favourites").action(async (id) => {
|
|
8566
|
+
try {
|
|
8567
|
+
const { device: dev } = await findDevice(id);
|
|
8568
|
+
await removeFavourite(dev.id);
|
|
8569
|
+
console.log(`\u2713 Removed ${dev.name} from favourites`);
|
|
8570
|
+
} catch (err) {
|
|
8571
|
+
console.error(`Failed to unfavourite device: ${err.message}`);
|
|
8572
|
+
process.exit(1);
|
|
8573
|
+
}
|
|
8574
|
+
});
|
|
8575
|
+
device.command("favourites").description("List favourite devices").action(async () => {
|
|
8576
|
+
try {
|
|
8577
|
+
const favIds = await getFavourites();
|
|
8578
|
+
if (favIds.length === 0) {
|
|
8579
|
+
console.log("No favourite devices.");
|
|
8580
|
+
return;
|
|
8581
|
+
}
|
|
8582
|
+
const { devices } = await getAllDevices();
|
|
8583
|
+
const favDevices = favIds.map((id) => devices.find((d) => d.id === id)).filter((d) => d !== void 0);
|
|
8584
|
+
if (favDevices.length === 0) {
|
|
8585
|
+
console.log("No favourite devices.");
|
|
8586
|
+
return;
|
|
8587
|
+
}
|
|
8588
|
+
printTable2(favDevices);
|
|
8589
|
+
} catch (err) {
|
|
8590
|
+
console.error(`Failed to list favourites: ${err.message}`);
|
|
8591
|
+
process.exit(1);
|
|
8592
|
+
}
|
|
8593
|
+
});
|
|
8485
8594
|
}
|
|
8486
8595
|
|
|
8487
8596
|
// src/commands/start.ts
|
package/package.json
CHANGED