@schuttdev/gigai 0.1.0-beta.17 → 0.1.0-beta.19
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.
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
AuthStore
|
|
4
|
-
} from "./chunk-OWDYY3IG.js";
|
|
5
|
-
import {
|
|
6
|
-
generatePairingCode,
|
|
7
|
-
validateAndPair
|
|
8
|
-
} from "./chunk-HN7WQY7K.js";
|
|
9
2
|
import {
|
|
10
3
|
ErrorCode,
|
|
11
4
|
GigaiConfigSchema,
|
|
12
5
|
GigaiError,
|
|
13
6
|
decrypt,
|
|
7
|
+
encrypt,
|
|
14
8
|
generateEncryptionKey
|
|
15
9
|
} from "./chunk-HIKBVSBK.js";
|
|
16
10
|
|
|
@@ -21,7 +15,9 @@ import cors from "@fastify/cors";
|
|
|
21
15
|
import rateLimit from "@fastify/rate-limit";
|
|
22
16
|
import multipart from "@fastify/multipart";
|
|
23
17
|
import fp from "fastify-plugin";
|
|
18
|
+
import { nanoid } from "nanoid";
|
|
24
19
|
import { randomBytes } from "crypto";
|
|
20
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
25
21
|
import fp2 from "fastify-plugin";
|
|
26
22
|
import fp3 from "fastify-plugin";
|
|
27
23
|
import { spawn } from "child_process";
|
|
@@ -37,7 +33,7 @@ import { spawn as spawn2 } from "child_process";
|
|
|
37
33
|
import { writeFile, readFile as readFile2, unlink, mkdir } from "fs/promises";
|
|
38
34
|
import { join as join2 } from "path";
|
|
39
35
|
import { tmpdir } from "os";
|
|
40
|
-
import { nanoid } from "nanoid";
|
|
36
|
+
import { nanoid as nanoid3 } from "nanoid";
|
|
41
37
|
import { readFile as readFile3 } from "fs/promises";
|
|
42
38
|
import { resolve as resolve3 } from "path";
|
|
43
39
|
import { spawn as spawn3 } from "child_process";
|
|
@@ -55,6 +51,71 @@ import { resolve as resolve6, join as join3 } from "path";
|
|
|
55
51
|
import { homedir, platform } from "os";
|
|
56
52
|
import { execFile as execFile2 } from "child_process";
|
|
57
53
|
import { promisify as promisify2 } from "util";
|
|
54
|
+
var AuthStore = class {
|
|
55
|
+
pairingCodes = /* @__PURE__ */ new Map();
|
|
56
|
+
sessions = /* @__PURE__ */ new Map();
|
|
57
|
+
cleanupInterval;
|
|
58
|
+
constructor() {
|
|
59
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
|
|
60
|
+
}
|
|
61
|
+
// Pairing codes
|
|
62
|
+
addPairingCode(code, ttlSeconds) {
|
|
63
|
+
const entry = {
|
|
64
|
+
code,
|
|
65
|
+
expiresAt: Date.now() + ttlSeconds * 1e3,
|
|
66
|
+
used: false
|
|
67
|
+
};
|
|
68
|
+
this.pairingCodes.set(code, entry);
|
|
69
|
+
return entry;
|
|
70
|
+
}
|
|
71
|
+
getPairingCode(code) {
|
|
72
|
+
return this.pairingCodes.get(code);
|
|
73
|
+
}
|
|
74
|
+
markPairingCodeUsed(code) {
|
|
75
|
+
const entry = this.pairingCodes.get(code);
|
|
76
|
+
if (entry) {
|
|
77
|
+
entry.used = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Sessions
|
|
81
|
+
createSession(orgUuid, ttlSeconds) {
|
|
82
|
+
const session = {
|
|
83
|
+
id: nanoid(32),
|
|
84
|
+
orgUuid,
|
|
85
|
+
token: nanoid(48),
|
|
86
|
+
expiresAt: Date.now() + ttlSeconds * 1e3,
|
|
87
|
+
lastActivity: Date.now()
|
|
88
|
+
};
|
|
89
|
+
this.sessions.set(session.token, session);
|
|
90
|
+
return session;
|
|
91
|
+
}
|
|
92
|
+
getSession(token) {
|
|
93
|
+
const session = this.sessions.get(token);
|
|
94
|
+
if (session) {
|
|
95
|
+
session.lastActivity = Date.now();
|
|
96
|
+
}
|
|
97
|
+
return session;
|
|
98
|
+
}
|
|
99
|
+
// Cleanup
|
|
100
|
+
cleanup() {
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
for (const [key, code] of this.pairingCodes) {
|
|
103
|
+
if (code.expiresAt < now) {
|
|
104
|
+
this.pairingCodes.delete(key);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const [key, session] of this.sessions) {
|
|
108
|
+
if (session.expiresAt < now) {
|
|
109
|
+
this.sessions.delete(key);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
destroy() {
|
|
114
|
+
clearInterval(this.cleanupInterval);
|
|
115
|
+
this.pairingCodes.clear();
|
|
116
|
+
this.sessions.clear();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
58
119
|
function connectWithToken(store, encryptedToken, orgUuid, encryptionKey, sessionTtlSeconds) {
|
|
59
120
|
let payload;
|
|
60
121
|
try {
|
|
@@ -94,6 +155,34 @@ function createAuthMiddleware(store) {
|
|
|
94
155
|
request.session = session;
|
|
95
156
|
};
|
|
96
157
|
}
|
|
158
|
+
var PAIRING_CODE_LENGTH = 8;
|
|
159
|
+
var PAIRING_CODE_CHARS = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
160
|
+
function generatePairingCode(store, ttlSeconds) {
|
|
161
|
+
let code = "";
|
|
162
|
+
const bytes = nanoid2(PAIRING_CODE_LENGTH);
|
|
163
|
+
for (let i = 0; i < PAIRING_CODE_LENGTH; i++) {
|
|
164
|
+
code += PAIRING_CODE_CHARS[bytes.charCodeAt(i) % PAIRING_CODE_CHARS.length];
|
|
165
|
+
}
|
|
166
|
+
store.addPairingCode(code, ttlSeconds);
|
|
167
|
+
return code;
|
|
168
|
+
}
|
|
169
|
+
function validateAndPair(store, code, orgUuid, encryptionKey, serverFingerprint) {
|
|
170
|
+
const entry = store.getPairingCode(code.toUpperCase());
|
|
171
|
+
if (!entry) {
|
|
172
|
+
throw new GigaiError(ErrorCode.PAIRING_INVALID, "Invalid pairing code");
|
|
173
|
+
}
|
|
174
|
+
if (entry.used) {
|
|
175
|
+
throw new GigaiError(ErrorCode.PAIRING_USED, "Pairing code already used");
|
|
176
|
+
}
|
|
177
|
+
if (entry.expiresAt < Date.now()) {
|
|
178
|
+
throw new GigaiError(ErrorCode.PAIRING_EXPIRED, "Pairing code expired");
|
|
179
|
+
}
|
|
180
|
+
store.markPairingCodeUsed(code.toUpperCase());
|
|
181
|
+
return encrypt(
|
|
182
|
+
{ orgUuid, serverFingerprint, createdAt: Date.now() },
|
|
183
|
+
encryptionKey
|
|
184
|
+
);
|
|
185
|
+
}
|
|
97
186
|
function registerAuthRoutes(server, store, config) {
|
|
98
187
|
const serverFingerprint = randomBytes(16).toString("hex");
|
|
99
188
|
server.post("/auth/pair", {
|
|
@@ -752,7 +841,7 @@ async function transferRoutes(server) {
|
|
|
752
841
|
if (!data) {
|
|
753
842
|
throw new GigaiError(ErrorCode.VALIDATION_ERROR, "No file uploaded");
|
|
754
843
|
}
|
|
755
|
-
const id =
|
|
844
|
+
const id = nanoid3(16);
|
|
756
845
|
const buffer = await data.toBuffer();
|
|
757
846
|
const filePath = join2(TRANSFER_DIR, id);
|
|
758
847
|
await writeFile(filePath, buffer);
|
|
@@ -1096,9 +1185,25 @@ async function runInit() {
|
|
|
1096
1185
|
} catch {
|
|
1097
1186
|
console.log(` Server starting in background (PID ${child.pid})`);
|
|
1098
1187
|
}
|
|
1099
|
-
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1188
|
+
let code;
|
|
1189
|
+
const maxRetries = 5;
|
|
1190
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
1191
|
+
try {
|
|
1192
|
+
const res = await fetch(`http://localhost:${port}/auth/pair/generate`);
|
|
1193
|
+
if (res.ok) {
|
|
1194
|
+
const data = await res.json();
|
|
1195
|
+
code = data.code;
|
|
1196
|
+
break;
|
|
1197
|
+
}
|
|
1198
|
+
} catch {
|
|
1199
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
if (!code) {
|
|
1203
|
+
console.log("\n Server is starting but not ready yet.");
|
|
1204
|
+
console.log(" Run 'gigai server pair' once it's up to get a pairing code.\n");
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1102
1207
|
console.log(`
|
|
1103
1208
|
Paste this into Claude to pair:
|
|
1104
1209
|
`);
|
|
@@ -1228,17 +1333,25 @@ async function unwrapTool(name) {
|
|
|
1228
1333
|
}
|
|
1229
1334
|
async function generateServerPairingCode(configPath) {
|
|
1230
1335
|
const { config } = await loadConfigFile(configPath);
|
|
1231
|
-
const
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1336
|
+
const port = config.server.port;
|
|
1337
|
+
try {
|
|
1338
|
+
const res = await fetch(`http://localhost:${port}/auth/pair/generate`);
|
|
1339
|
+
if (!res.ok) {
|
|
1340
|
+
const body = await res.text();
|
|
1341
|
+
throw new Error(`Server returned ${res.status}: ${body}`);
|
|
1342
|
+
}
|
|
1343
|
+
const data = await res.json();
|
|
1344
|
+
console.log(`
|
|
1345
|
+
Pairing code: ${data.code}`);
|
|
1346
|
+
console.log(`Expires in ${data.expiresIn / 60} minutes.`);
|
|
1347
|
+
} catch (e) {
|
|
1348
|
+
if (e.message.includes("fetch failed") || e.message.includes("ECONNREFUSED")) {
|
|
1349
|
+
console.error("Server is not running. Start it with: gigai server start");
|
|
1350
|
+
} else {
|
|
1351
|
+
console.error(`Error: ${e.message}`);
|
|
1352
|
+
}
|
|
1353
|
+
process.exitCode = 1;
|
|
1354
|
+
}
|
|
1242
1355
|
}
|
|
1243
1356
|
var execFileAsync2 = promisify2(execFile2);
|
|
1244
1357
|
function getGigaiBin() {
|
|
@@ -1359,6 +1472,27 @@ async function uninstallDaemon() {
|
|
|
1359
1472
|
}
|
|
1360
1473
|
}
|
|
1361
1474
|
}
|
|
1475
|
+
async function stopServer() {
|
|
1476
|
+
const { execFileSync } = await import("child_process");
|
|
1477
|
+
let pids = [];
|
|
1478
|
+
try {
|
|
1479
|
+
const out = execFileSync("pgrep", ["-f", "gigai server start"], { encoding: "utf8" });
|
|
1480
|
+
pids = out.trim().split("\n").map(Number).filter((pid) => pid && pid !== process.pid);
|
|
1481
|
+
} catch {
|
|
1482
|
+
}
|
|
1483
|
+
if (pids.length === 0) {
|
|
1484
|
+
console.log("No running gigai server found.");
|
|
1485
|
+
return;
|
|
1486
|
+
}
|
|
1487
|
+
for (const pid of pids) {
|
|
1488
|
+
try {
|
|
1489
|
+
process.kill(pid, "SIGTERM");
|
|
1490
|
+
console.log(`Stopped gigai server (PID ${pid})`);
|
|
1491
|
+
} catch (e) {
|
|
1492
|
+
console.error(`Failed to stop PID ${pid}: ${e.message}`);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1362
1496
|
async function startServer() {
|
|
1363
1497
|
const { values } = parseArgs({
|
|
1364
1498
|
options: {
|
|
@@ -1418,6 +1552,7 @@ export {
|
|
|
1418
1552
|
loadConfig,
|
|
1419
1553
|
runInit,
|
|
1420
1554
|
startServer,
|
|
1555
|
+
stopServer,
|
|
1421
1556
|
uninstallDaemon,
|
|
1422
1557
|
unwrapTool,
|
|
1423
1558
|
wrapCli,
|
package/dist/index.js
CHANGED
|
@@ -577,7 +577,7 @@ function runCitty() {
|
|
|
577
577
|
dev: { type: "boolean", description: "Development mode (no HTTPS)" }
|
|
578
578
|
},
|
|
579
579
|
async run({ args }) {
|
|
580
|
-
const { startServer } = await import("./dist-
|
|
580
|
+
const { startServer } = await import("./dist-IQVGU6KW.js");
|
|
581
581
|
const extraArgs = [];
|
|
582
582
|
if (args.config) extraArgs.push("--config", args.config);
|
|
583
583
|
if (args.dev) extraArgs.push("--dev");
|
|
@@ -588,7 +588,7 @@ function runCitty() {
|
|
|
588
588
|
init: defineCommand({
|
|
589
589
|
meta: { name: "init", description: "Interactive setup wizard" },
|
|
590
590
|
async run() {
|
|
591
|
-
const { runInit } = await import("./dist-
|
|
591
|
+
const { runInit } = await import("./dist-IQVGU6KW.js");
|
|
592
592
|
await runInit();
|
|
593
593
|
}
|
|
594
594
|
}),
|
|
@@ -598,7 +598,7 @@ function runCitty() {
|
|
|
598
598
|
config: { type: "string", alias: "c", description: "Config file path" }
|
|
599
599
|
},
|
|
600
600
|
async run({ args }) {
|
|
601
|
-
const { generateServerPairingCode } = await import("./dist-
|
|
601
|
+
const { generateServerPairingCode } = await import("./dist-IQVGU6KW.js");
|
|
602
602
|
await generateServerPairingCode(args.config);
|
|
603
603
|
}
|
|
604
604
|
}),
|
|
@@ -608,17 +608,24 @@ function runCitty() {
|
|
|
608
608
|
config: { type: "string", alias: "c", description: "Config file path" }
|
|
609
609
|
},
|
|
610
610
|
async run({ args }) {
|
|
611
|
-
const { installDaemon } = await import("./dist-
|
|
611
|
+
const { installDaemon } = await import("./dist-IQVGU6KW.js");
|
|
612
612
|
await installDaemon(args.config);
|
|
613
613
|
}
|
|
614
614
|
}),
|
|
615
615
|
uninstall: defineCommand({
|
|
616
616
|
meta: { name: "uninstall", description: "Remove background service" },
|
|
617
617
|
async run() {
|
|
618
|
-
const { uninstallDaemon } = await import("./dist-
|
|
618
|
+
const { uninstallDaemon } = await import("./dist-IQVGU6KW.js");
|
|
619
619
|
await uninstallDaemon();
|
|
620
620
|
}
|
|
621
621
|
}),
|
|
622
|
+
stop: defineCommand({
|
|
623
|
+
meta: { name: "stop", description: "Stop the running gigai server" },
|
|
624
|
+
async run() {
|
|
625
|
+
const { stopServer } = await import("./dist-IQVGU6KW.js");
|
|
626
|
+
await stopServer();
|
|
627
|
+
}
|
|
628
|
+
}),
|
|
622
629
|
status: defineCommand({
|
|
623
630
|
meta: { name: "status", description: "Show server status" },
|
|
624
631
|
async run() {
|
|
@@ -642,21 +649,21 @@ function runCitty() {
|
|
|
642
649
|
cli: defineCommand({
|
|
643
650
|
meta: { name: "cli", description: "Wrap a CLI command" },
|
|
644
651
|
async run() {
|
|
645
|
-
const { wrapCli } = await import("./dist-
|
|
652
|
+
const { wrapCli } = await import("./dist-IQVGU6KW.js");
|
|
646
653
|
await wrapCli();
|
|
647
654
|
}
|
|
648
655
|
}),
|
|
649
656
|
mcp: defineCommand({
|
|
650
657
|
meta: { name: "mcp", description: "Wrap an MCP server" },
|
|
651
658
|
async run() {
|
|
652
|
-
const { wrapMcp } = await import("./dist-
|
|
659
|
+
const { wrapMcp } = await import("./dist-IQVGU6KW.js");
|
|
653
660
|
await wrapMcp();
|
|
654
661
|
}
|
|
655
662
|
}),
|
|
656
663
|
script: defineCommand({
|
|
657
664
|
meta: { name: "script", description: "Wrap a script" },
|
|
658
665
|
async run() {
|
|
659
|
-
const { wrapScript } = await import("./dist-
|
|
666
|
+
const { wrapScript } = await import("./dist-IQVGU6KW.js");
|
|
660
667
|
await wrapScript();
|
|
661
668
|
}
|
|
662
669
|
}),
|
|
@@ -666,7 +673,7 @@ function runCitty() {
|
|
|
666
673
|
path: { type: "positional", description: "Path to config file", required: true }
|
|
667
674
|
},
|
|
668
675
|
async run({ args }) {
|
|
669
|
-
const { wrapImport } = await import("./dist-
|
|
676
|
+
const { wrapImport } = await import("./dist-IQVGU6KW.js");
|
|
670
677
|
await wrapImport(args.path);
|
|
671
678
|
}
|
|
672
679
|
})
|
|
@@ -678,7 +685,7 @@ function runCitty() {
|
|
|
678
685
|
name: { type: "positional", description: "Tool name", required: true }
|
|
679
686
|
},
|
|
680
687
|
async run({ args }) {
|
|
681
|
-
const { unwrapTool } = await import("./dist-
|
|
688
|
+
const { unwrapTool } = await import("./dist-IQVGU6KW.js");
|
|
682
689
|
await unwrapTool(args.name);
|
|
683
690
|
}
|
|
684
691
|
});
|
package/package.json
CHANGED
package/dist/chunk-HN7WQY7K.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
ErrorCode,
|
|
4
|
-
GigaiError,
|
|
5
|
-
encrypt
|
|
6
|
-
} from "./chunk-HIKBVSBK.js";
|
|
7
|
-
|
|
8
|
-
// ../server/dist/chunk-54TEF6CS.mjs
|
|
9
|
-
import { nanoid } from "nanoid";
|
|
10
|
-
var PAIRING_CODE_LENGTH = 8;
|
|
11
|
-
var PAIRING_CODE_CHARS = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
12
|
-
function generatePairingCode(store, ttlSeconds) {
|
|
13
|
-
let code = "";
|
|
14
|
-
const bytes = nanoid(PAIRING_CODE_LENGTH);
|
|
15
|
-
for (let i = 0; i < PAIRING_CODE_LENGTH; i++) {
|
|
16
|
-
code += PAIRING_CODE_CHARS[bytes.charCodeAt(i) % PAIRING_CODE_CHARS.length];
|
|
17
|
-
}
|
|
18
|
-
store.addPairingCode(code, ttlSeconds);
|
|
19
|
-
return code;
|
|
20
|
-
}
|
|
21
|
-
function validateAndPair(store, code, orgUuid, encryptionKey, serverFingerprint) {
|
|
22
|
-
const entry = store.getPairingCode(code.toUpperCase());
|
|
23
|
-
if (!entry) {
|
|
24
|
-
throw new GigaiError(ErrorCode.PAIRING_INVALID, "Invalid pairing code");
|
|
25
|
-
}
|
|
26
|
-
if (entry.used) {
|
|
27
|
-
throw new GigaiError(ErrorCode.PAIRING_USED, "Pairing code already used");
|
|
28
|
-
}
|
|
29
|
-
if (entry.expiresAt < Date.now()) {
|
|
30
|
-
throw new GigaiError(ErrorCode.PAIRING_EXPIRED, "Pairing code expired");
|
|
31
|
-
}
|
|
32
|
-
store.markPairingCodeUsed(code.toUpperCase());
|
|
33
|
-
return encrypt(
|
|
34
|
-
{ orgUuid, serverFingerprint, createdAt: Date.now() },
|
|
35
|
-
encryptionKey
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export {
|
|
40
|
-
generatePairingCode,
|
|
41
|
-
validateAndPair
|
|
42
|
-
};
|
package/dist/chunk-OWDYY3IG.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// ../server/dist/chunk-RZTCSUFS.mjs
|
|
4
|
-
import { nanoid } from "nanoid";
|
|
5
|
-
var AuthStore = class {
|
|
6
|
-
pairingCodes = /* @__PURE__ */ new Map();
|
|
7
|
-
sessions = /* @__PURE__ */ new Map();
|
|
8
|
-
cleanupInterval;
|
|
9
|
-
constructor() {
|
|
10
|
-
this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
|
|
11
|
-
}
|
|
12
|
-
// Pairing codes
|
|
13
|
-
addPairingCode(code, ttlSeconds) {
|
|
14
|
-
const entry = {
|
|
15
|
-
code,
|
|
16
|
-
expiresAt: Date.now() + ttlSeconds * 1e3,
|
|
17
|
-
used: false
|
|
18
|
-
};
|
|
19
|
-
this.pairingCodes.set(code, entry);
|
|
20
|
-
return entry;
|
|
21
|
-
}
|
|
22
|
-
getPairingCode(code) {
|
|
23
|
-
return this.pairingCodes.get(code);
|
|
24
|
-
}
|
|
25
|
-
markPairingCodeUsed(code) {
|
|
26
|
-
const entry = this.pairingCodes.get(code);
|
|
27
|
-
if (entry) {
|
|
28
|
-
entry.used = true;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
// Sessions
|
|
32
|
-
createSession(orgUuid, ttlSeconds) {
|
|
33
|
-
const session = {
|
|
34
|
-
id: nanoid(32),
|
|
35
|
-
orgUuid,
|
|
36
|
-
token: nanoid(48),
|
|
37
|
-
expiresAt: Date.now() + ttlSeconds * 1e3,
|
|
38
|
-
lastActivity: Date.now()
|
|
39
|
-
};
|
|
40
|
-
this.sessions.set(session.token, session);
|
|
41
|
-
return session;
|
|
42
|
-
}
|
|
43
|
-
getSession(token) {
|
|
44
|
-
const session = this.sessions.get(token);
|
|
45
|
-
if (session) {
|
|
46
|
-
session.lastActivity = Date.now();
|
|
47
|
-
}
|
|
48
|
-
return session;
|
|
49
|
-
}
|
|
50
|
-
// Cleanup
|
|
51
|
-
cleanup() {
|
|
52
|
-
const now = Date.now();
|
|
53
|
-
for (const [key, code] of this.pairingCodes) {
|
|
54
|
-
if (code.expiresAt < now) {
|
|
55
|
-
this.pairingCodes.delete(key);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
for (const [key, session] of this.sessions) {
|
|
59
|
-
if (session.expiresAt < now) {
|
|
60
|
-
this.sessions.delete(key);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
destroy() {
|
|
65
|
-
clearInterval(this.cleanupInterval);
|
|
66
|
-
this.pairingCodes.clear();
|
|
67
|
-
this.sessions.clear();
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
export {
|
|
72
|
-
AuthStore
|
|
73
|
-
};
|