@commit451/salamander 1.2.1 → 1.3.1
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/README.md +42 -42
- package/bin/salamander.js +1 -1
- package/dist/commands/runner-selection.d.ts +1 -1
- package/dist/commands/runner-selection.d.ts.map +1 -1
- package/dist/commands/runner-selection.js +75 -12
- package/dist/commands/runner-selection.js.map +1 -1
- package/dist/config/firebase.d.ts +2 -0
- package/dist/config/firebase.d.ts.map +1 -1
- package/dist/config/firebase.js +16 -0
- package/dist/config/firebase.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/services/auth.d.ts +1 -0
- package/dist/services/auth.d.ts.map +1 -1
- package/dist/services/auth.js +51 -61
- package/dist/services/auth.js.map +1 -1
- package/dist/services/command-listener.d.ts +1 -0
- package/dist/services/command-listener.d.ts.map +1 -1
- package/dist/services/command-listener.js +30 -7
- package/dist/services/command-listener.js.map +1 -1
- package/dist/services/crypto.d.ts +52 -0
- package/dist/services/crypto.d.ts.map +1 -0
- package/dist/services/crypto.js +104 -0
- package/dist/services/crypto.js.map +1 -0
- package/dist/services/key-manager.d.ts +45 -0
- package/dist/services/key-manager.d.ts.map +1 -0
- package/dist/services/key-manager.js +123 -0
- package/dist/services/key-manager.js.map +1 -0
- package/dist/services/multi-device-key-manager.d.ts +56 -0
- package/dist/services/multi-device-key-manager.d.ts.map +1 -0
- package/dist/services/multi-device-key-manager.js +159 -0
- package/dist/services/multi-device-key-manager.js.map +1 -0
- package/dist/services/runner.d.ts.map +1 -1
- package/dist/services/runner.js +56 -19
- package/dist/services/runner.js.map +1 -1
- package/dist/utils/file-persistence.d.ts +19 -0
- package/dist/utils/file-persistence.d.ts.map +1 -0
- package/dist/utils/file-persistence.js +64 -0
- package/dist/utils/file-persistence.js.map +1 -0
- package/dist/utils/storage.d.ts +5 -0
- package/dist/utils/storage.d.ts.map +1 -1
- package/dist/utils/storage.js +14 -0
- package/dist/utils/storage.js.map +1 -1
- package/package.json +52 -52
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { CryptoService } from './crypto.js';
|
|
2
|
+
import { StorageService } from '../utils/storage.js';
|
|
3
|
+
export class MultiDeviceKeyManagerService {
|
|
4
|
+
static KEYS_STORAGE_KEY = 'salamander_multi_device_keys';
|
|
5
|
+
static KEY_EXPIRY_DAYS = 30;
|
|
6
|
+
/**
|
|
7
|
+
* Initialize keys for a new runner (CLI side)
|
|
8
|
+
*/
|
|
9
|
+
static async initializeRunnerKeys(runnerId) {
|
|
10
|
+
const ecdhKeyPair = CryptoService.generateECDHKeyPair();
|
|
11
|
+
const keyData = {
|
|
12
|
+
ecdhKeyPair,
|
|
13
|
+
sharedSecrets: {},
|
|
14
|
+
keyHashes: {},
|
|
15
|
+
createdAt: Date.now()
|
|
16
|
+
};
|
|
17
|
+
await this.storeRunnerKeys(runnerId, keyData);
|
|
18
|
+
return ecdhKeyPair;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Register a new device and derive shared secret
|
|
22
|
+
*/
|
|
23
|
+
static async registerDevice(runnerId, deviceKey) {
|
|
24
|
+
const keyData = await this.getRunnerKeys(runnerId);
|
|
25
|
+
if (!keyData) {
|
|
26
|
+
throw new Error(`No keys found for runner ${runnerId}`);
|
|
27
|
+
}
|
|
28
|
+
// Derive shared secret with this device
|
|
29
|
+
const sharedSecret = CryptoService.deriveSharedSecret(keyData.ecdhKeyPair.privateKey, deviceKey.publicKey);
|
|
30
|
+
const keyHash = CryptoService.createKeyHash(sharedSecret);
|
|
31
|
+
// Verify the key hash matches what the device expects
|
|
32
|
+
if (keyHash !== deviceKey.keyHash) {
|
|
33
|
+
throw new Error('Key hash mismatch during device registration');
|
|
34
|
+
}
|
|
35
|
+
// Store the shared secret for this device
|
|
36
|
+
keyData.sharedSecrets[deviceKey.deviceId] = sharedSecret;
|
|
37
|
+
keyData.keyHashes[deviceKey.deviceId] = keyHash;
|
|
38
|
+
await this.storeRunnerKeys(runnerId, keyData);
|
|
39
|
+
console.log(`✓ Device ${deviceKey.deviceId} registered for runner ${runnerId}`);
|
|
40
|
+
return sharedSecret;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Remove a device from the runner
|
|
44
|
+
*/
|
|
45
|
+
static async removeDevice(runnerId, deviceId) {
|
|
46
|
+
const keyData = await this.getRunnerKeys(runnerId);
|
|
47
|
+
if (!keyData) {
|
|
48
|
+
return; // No keys to clean up
|
|
49
|
+
}
|
|
50
|
+
delete keyData.sharedSecrets[deviceId];
|
|
51
|
+
delete keyData.keyHashes[deviceId];
|
|
52
|
+
await this.storeRunnerKeys(runnerId, keyData);
|
|
53
|
+
console.log(`Device ${deviceId} removed from runner ${runnerId}`);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get shared secret for specific device
|
|
57
|
+
*/
|
|
58
|
+
static async getSharedSecret(runnerId, deviceId) {
|
|
59
|
+
const keyData = await this.getRunnerKeys(runnerId);
|
|
60
|
+
if (!keyData) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
// Check if keys are expired
|
|
64
|
+
const daysSinceCreation = (Date.now() - keyData.createdAt) / (1000 * 60 * 60 * 24);
|
|
65
|
+
if (daysSinceCreation > this.KEY_EXPIRY_DAYS) {
|
|
66
|
+
console.warn(`Keys for runner ${runnerId} have expired. Consider key rotation.`);
|
|
67
|
+
}
|
|
68
|
+
return keyData.sharedSecrets[deviceId] || null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get all registered device IDs for a runner
|
|
72
|
+
*/
|
|
73
|
+
static async getRegisteredDevices(runnerId) {
|
|
74
|
+
const keyData = await this.getRunnerKeys(runnerId);
|
|
75
|
+
if (!keyData) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
return Object.keys(keyData.sharedSecrets);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Encrypt command for specific device
|
|
82
|
+
*/
|
|
83
|
+
static async encryptForDevice(runnerId, deviceId, command) {
|
|
84
|
+
const sharedSecret = await this.getSharedSecret(runnerId, deviceId);
|
|
85
|
+
if (!sharedSecret) {
|
|
86
|
+
throw new Error(`No shared secret found for device ${deviceId} on runner ${runnerId}`);
|
|
87
|
+
}
|
|
88
|
+
return CryptoService.safeEncrypt(command, sharedSecret);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Encrypt command for all registered devices
|
|
92
|
+
*/
|
|
93
|
+
static async encryptForAllDevices(runnerId, command) {
|
|
94
|
+
const keyData = await this.getRunnerKeys(runnerId);
|
|
95
|
+
if (!keyData) {
|
|
96
|
+
throw new Error(`No keys found for runner ${runnerId}`);
|
|
97
|
+
}
|
|
98
|
+
const encryptedCommands = {};
|
|
99
|
+
for (const [deviceId, sharedSecret] of Object.entries(keyData.sharedSecrets)) {
|
|
100
|
+
try {
|
|
101
|
+
encryptedCommands[deviceId] = CryptoService.safeEncrypt(command, sharedSecret);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.warn(`Failed to encrypt command for device ${deviceId}: ${error}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (Object.keys(encryptedCommands).length === 0) {
|
|
108
|
+
throw new Error(`No devices registered for runner ${runnerId}`);
|
|
109
|
+
}
|
|
110
|
+
return encryptedCommands;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Decrypt command from specific device
|
|
114
|
+
*/
|
|
115
|
+
static async decryptFromDevice(runnerId, deviceId, encryptedCommand) {
|
|
116
|
+
const sharedSecret = await this.getSharedSecret(runnerId, deviceId);
|
|
117
|
+
if (!sharedSecret) {
|
|
118
|
+
throw new Error(`No shared secret found for device ${deviceId} on runner ${runnerId}`);
|
|
119
|
+
}
|
|
120
|
+
return CryptoService.safeDecrypt(encryptedCommand, sharedSecret);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if runner has any registered devices
|
|
124
|
+
*/
|
|
125
|
+
static async hasRegisteredDevices(runnerId) {
|
|
126
|
+
const devices = await this.getRegisteredDevices(runnerId);
|
|
127
|
+
return devices.length > 0;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Clean up all keys for a runner
|
|
131
|
+
*/
|
|
132
|
+
static async removeRunnerKeys(runnerId) {
|
|
133
|
+
const allKeys = await this.getAllStoredKeys();
|
|
134
|
+
delete allKeys[runnerId];
|
|
135
|
+
await StorageService.set(this.KEYS_STORAGE_KEY, allKeys);
|
|
136
|
+
console.log(`Cleaned up all keys for runner ${runnerId}`);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get CLI's public key for a runner
|
|
140
|
+
*/
|
|
141
|
+
static async getCliPublicKey(runnerId) {
|
|
142
|
+
const keyData = await this.getRunnerKeys(runnerId);
|
|
143
|
+
return keyData?.ecdhKeyPair.publicKey || null;
|
|
144
|
+
}
|
|
145
|
+
// Private helper methods
|
|
146
|
+
static async getRunnerKeys(runnerId) {
|
|
147
|
+
const allKeys = await this.getAllStoredKeys();
|
|
148
|
+
return allKeys[runnerId] || null;
|
|
149
|
+
}
|
|
150
|
+
static async storeRunnerKeys(runnerId, keys) {
|
|
151
|
+
const allKeys = await this.getAllStoredKeys();
|
|
152
|
+
allKeys[runnerId] = keys;
|
|
153
|
+
await StorageService.set(this.KEYS_STORAGE_KEY, allKeys);
|
|
154
|
+
}
|
|
155
|
+
static async getAllStoredKeys() {
|
|
156
|
+
return (await StorageService.get(this.KEYS_STORAGE_KEY)) ?? {};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=multi-device-key-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-device-key-manager.js","sourceRoot":"","sources":["../../src/services/multi-device-key-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/services/runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/services/runner.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,oBAAoB,EAAC,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAC,KAAK,gBAAgB,EAAE,KAAK,MAAM,EAAa,MAAM,oBAAoB,CAAC;AAKlF,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAa;WAE1C,aAAa,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;WAkBlC,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;WAmDrD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAK7C,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAMpD,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAQ5F,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAOrE,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAavF,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI;IAiE9F,OAAO,CAAC,MAAM,CAAC,WAAW;IAiB1B,OAAO,CAAC,MAAM,CAAC,eAAe;CAWjC"}
|
package/dist/services/runner.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { collection, doc, getDocs, onSnapshot, orderBy, query, where, } from 'firebase/firestore';
|
|
2
|
+
import chalk from 'chalk';
|
|
2
3
|
import { db } from '../config/firebase.js';
|
|
3
4
|
import { AuthService } from './auth.js';
|
|
4
5
|
import { ApiService } from './api.js';
|
|
@@ -93,27 +94,63 @@ export class RunnerService {
|
|
|
93
94
|
await ApiService.createRunnerMessage(runnerId, data);
|
|
94
95
|
}
|
|
95
96
|
static listenToRunner(runnerId, callback) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
callback(null);
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
// Swallow transient NOT_FOUND/unlisten race errors from Firestore stream restarts
|
|
107
|
-
(error) => {
|
|
108
|
-
const msg = String(error?.message || '');
|
|
109
|
-
if (error?.code === 'not-found' ||
|
|
110
|
-
msg.includes('Target id not found')) {
|
|
111
|
-
// no-op; listener cleanup or document delete races can cause this
|
|
97
|
+
let unsubscribe = null;
|
|
98
|
+
let stopped = false;
|
|
99
|
+
let retryCount = 0;
|
|
100
|
+
const subscribe = () => {
|
|
101
|
+
if (stopped)
|
|
112
102
|
return;
|
|
103
|
+
const runnerDoc = doc(db, this.RUNNERS_COLLECTION, runnerId);
|
|
104
|
+
unsubscribe = onSnapshot(runnerDoc, (snapshot) => {
|
|
105
|
+
if (retryCount > 0) {
|
|
106
|
+
console.log(chalk.green('✅ Firestore connection re-established'));
|
|
107
|
+
}
|
|
108
|
+
retryCount = 0;
|
|
109
|
+
if (snapshot.exists()) {
|
|
110
|
+
const runner = this.docToRunner(snapshot.data(), snapshot.id);
|
|
111
|
+
callback(runner);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
callback(null);
|
|
115
|
+
}
|
|
116
|
+
}, (error) => {
|
|
117
|
+
const msg = String(error?.message || '');
|
|
118
|
+
// Swallow transient NOT_FOUND/unlisten race errors from Firestore stream restarts
|
|
119
|
+
if (error?.code === 'not-found' ||
|
|
120
|
+
msg.includes('Target id not found')) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (stopped)
|
|
124
|
+
return;
|
|
125
|
+
retryCount++;
|
|
126
|
+
const delay = Math.min(1000 * Math.pow(2, retryCount - 1), 30000);
|
|
127
|
+
console.log(chalk.yellow(`⚠️ Firestore listener error (attempt ${retryCount}), reconnecting in ${delay / 1000}s...`));
|
|
128
|
+
console.log(chalk.gray(` ${error.message}`));
|
|
129
|
+
// Tear down the failed listener before retrying
|
|
130
|
+
if (unsubscribe) {
|
|
131
|
+
try {
|
|
132
|
+
unsubscribe();
|
|
133
|
+
}
|
|
134
|
+
catch { }
|
|
135
|
+
unsubscribe = null;
|
|
136
|
+
}
|
|
137
|
+
setTimeout(() => {
|
|
138
|
+
if (!stopped)
|
|
139
|
+
subscribe();
|
|
140
|
+
}, delay);
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
subscribe();
|
|
144
|
+
return () => {
|
|
145
|
+
stopped = true;
|
|
146
|
+
if (unsubscribe) {
|
|
147
|
+
try {
|
|
148
|
+
unsubscribe();
|
|
149
|
+
}
|
|
150
|
+
catch { }
|
|
151
|
+
unsubscribe = null;
|
|
113
152
|
}
|
|
114
|
-
|
|
115
|
-
throw error;
|
|
116
|
-
});
|
|
153
|
+
};
|
|
117
154
|
}
|
|
118
155
|
static docToRunner(data, id) {
|
|
119
156
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/services/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAC,EAAE,EAAC,MAAM,uBAAuB,CAAC;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,WAAW,CAAC;AACtC,OAAO,EAAC,UAAU,EAAuB,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAqC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAC,gBAAgB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAC,cAAc,EAAE,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAEnE,MAAM,OAAO,aAAa;IACd,MAAM,CAAU,kBAAkB,GAAG,SAAS,CAAC;IAEvD,MAAM,CAAC,KAAK,CAAC,aAAa;QACtB,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;QAClC,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QACpC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,CAAC,GAAG,KAAK,CACX,UAAU,CAAC,EAAE,EAAE,IAAI,CAAC,kBAAkB,CAAC,EACvC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,EAC7B,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,QAAQ,CAAC,EAClC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAC9B,CAAC;QAEF,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;QACvC,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAsB;QAC5C,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAC;QAE1C,mCAAmC;QACnC,IAAI,cAAsB,CAAC;QAC3B,MAAM,gBAAgB,GAAG,MAAM,cAAc,EAAE,CAAC;QAEhD,IAAI,gBAAgB,EAAE,cAAc,EAAE,CAAC;YACnC,cAAc,GAAG,gBAAgB,CAAC,cAAc,CAAC;QACrD,CAAC;aAAM,CAAC;YACJ,sCAAsC;YACtC,cAAc,GAAG,iBAAiB,CAAC,oBAAoB,EAAE,CAAC;YAE1D,kBAAkB;YAClB,MAAM,cAAc,CAAC,EAAC,cAAc,EAAC,CAAC,CAAC;QAC3C,CAAC;QAED,6BAA6B;QAC7B,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;QAE1F,qDAAqD;QACrD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,YAAY,CAAC;YAC3C,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,SAAS,EAAE,QAAQ;YACnB,WAAW,EAAE,UAAU;YACvB,sBAAsB,EAAE,sBAAsB;YAC9C,UAAU,EAAE,IAAI,CAAC,UAAU;SAC9B,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC;QAE7B,OAAO;YACH,EAAE,EAAE,QAAQ;YACZ,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,MAAM;YACN,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,SAAS,EAAE,IAAI,IAAI,EAAE;YACrB,QAAQ,EAAE,IAAI,IAAI,EAAE;YACpB,SAAS,EAAE,QAAQ;YACnB,WAAW,EAAE,UAAU;SAC1B,CAAC;IACN,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,QAAgB;QACtC,oCAAoC;QACpC,MAAM,UAAU,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,QAAgB;QAC7C,MAAM,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE;YACpC,mBAAmB,EAAE,IAAI;SAC5B,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,QAAgB,EAAE,MAAc,EAAE,QAAiB;QACrF,MAAM,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE;YACpC,cAAc,EAAE,IAAI;YACpB,WAAW,EAAE,MAAM,IAAI,EAAE;YACzB,QAAQ,EAAE,QAAQ;SACrB,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,cAAsB;QAC9D,MAAM,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE;YACpC,cAAc;SACjB,CAAC,CAAC;IACP,CAAC;IAGD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,IAA0B;QACnE,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,UAAU,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,QAAgB,EAAE,QAAyC;QAC7E,MAAM,SAAS,GAAG,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/services/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Persistence } from 'firebase/auth';
|
|
2
|
+
/**
|
|
3
|
+
* File-based persistence for Firebase Auth in Node.js.
|
|
4
|
+
* Implements the internal PersistenceInternal interface so the SDK
|
|
5
|
+
* can persist and restore auth state across process restarts.
|
|
6
|
+
*/
|
|
7
|
+
export declare class FilePersistence implements Persistence {
|
|
8
|
+
static readonly type: "LOCAL";
|
|
9
|
+
readonly type: "LOCAL";
|
|
10
|
+
_isAvailable(): Promise<boolean>;
|
|
11
|
+
_set(key: string, value: unknown): Promise<void>;
|
|
12
|
+
_get<T>(key: string): Promise<T | null>;
|
|
13
|
+
_remove(key: string): Promise<void>;
|
|
14
|
+
_addListener(_key: string, _listener: (value: unknown) => void): void;
|
|
15
|
+
_removeListener(_key: string, _listener: (value: unknown) => void): void;
|
|
16
|
+
}
|
|
17
|
+
export declare const filePersistence: FilePersistence;
|
|
18
|
+
export declare function clearAuthStorage(): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=file-persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-persistence.d.ts","sourceRoot":"","sources":["../../src/utils/file-persistence.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAiB/C;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,WAAW;IAC/C,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACxC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IAE3B,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IASvC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAIrE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;CAG3E;AAED,eAAO,MAAM,eAAe,iBAAwB,CAAC;AAErD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAOtD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
const AUTH_DIR = join(homedir(), '.salamander', 'auth');
|
|
5
|
+
async function ensureAuthDir() {
|
|
6
|
+
try {
|
|
7
|
+
await fs.access(AUTH_DIR);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
await fs.mkdir(AUTH_DIR, { recursive: true });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function keyToPath(key) {
|
|
14
|
+
const safe = key.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
15
|
+
return join(AUTH_DIR, `${safe}.json`);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* File-based persistence for Firebase Auth in Node.js.
|
|
19
|
+
* Implements the internal PersistenceInternal interface so the SDK
|
|
20
|
+
* can persist and restore auth state across process restarts.
|
|
21
|
+
*/
|
|
22
|
+
export class FilePersistence {
|
|
23
|
+
static type = 'LOCAL';
|
|
24
|
+
type = 'LOCAL';
|
|
25
|
+
async _isAvailable() {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
async _set(key, value) {
|
|
29
|
+
await ensureAuthDir();
|
|
30
|
+
await fs.writeFile(keyToPath(key), JSON.stringify(value), 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
async _get(key) {
|
|
33
|
+
try {
|
|
34
|
+
const data = await fs.readFile(keyToPath(key), 'utf-8');
|
|
35
|
+
return JSON.parse(data);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async _remove(key) {
|
|
42
|
+
try {
|
|
43
|
+
await fs.unlink(keyToPath(key));
|
|
44
|
+
}
|
|
45
|
+
catch { }
|
|
46
|
+
}
|
|
47
|
+
_addListener(_key, _listener) {
|
|
48
|
+
// No cross-tab/process sync needed for a CLI
|
|
49
|
+
}
|
|
50
|
+
_removeListener(_key, _listener) {
|
|
51
|
+
// No cross-tab/process sync needed for a CLI
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export const filePersistence = new FilePersistence();
|
|
55
|
+
export async function clearAuthStorage() {
|
|
56
|
+
try {
|
|
57
|
+
const files = await fs.readdir(AUTH_DIR);
|
|
58
|
+
for (const file of files) {
|
|
59
|
+
await fs.unlink(join(AUTH_DIR, file));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch { }
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=file-persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-persistence.js","sourceRoot":"","sources":["../../src/utils/file-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,IAAI,EAAE,EAAC,MAAM,IAAI,CAAC;AAClC,OAAO,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAC1B,OAAO,EAAC,OAAO,EAAC,MAAM,IAAI,CAAC;AAG3B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;AAExD,KAAK,UAAU,aAAa;IACxB,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAChD,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,eAAe;IACxB,MAAM,CAAU,IAAI,GAAG,OAAgB,CAAC;IAC/B,IAAI,GAAG,OAAgB,CAAC;IAEjC,KAAK,CAAC,YAAY;QACd,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW,EAAE,KAAc;QAClC,MAAM,aAAa,EAAE,CAAC;QACtB,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAW;QACrB,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YACxD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACrB,IAAI,CAAC;YACD,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACd,CAAC;IAED,YAAY,CAAC,IAAY,EAAE,SAAmC;QAC1D,6CAA6C;IACjD,CAAC;IAED,eAAe,CAAC,IAAY,EAAE,SAAmC;QAC7D,6CAA6C;IACjD,CAAC;;AAGL,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,gBAAgB;IAClC,IAAI,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACd,CAAC"}
|
package/dist/utils/storage.d.ts
CHANGED
|
@@ -3,4 +3,9 @@ export interface StoredEncryption {
|
|
|
3
3
|
}
|
|
4
4
|
export declare function saveEncryption(encryption: StoredEncryption): Promise<void>;
|
|
5
5
|
export declare function loadEncryption(): Promise<StoredEncryption | null>;
|
|
6
|
+
export interface StoredConfig {
|
|
7
|
+
defaultRunnerId?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function saveConfig(config: StoredConfig): Promise<void>;
|
|
10
|
+
export declare function loadConfig(): Promise<StoredConfig | null>;
|
|
6
11
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAUD,wBAAsB,cAAc,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhF;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAOvE"}
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAUD,wBAAsB,cAAc,CAAC,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhF;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAOvE;AAID,MAAM,WAAW,YAAY;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpE;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAO/D"}
|
package/dist/utils/storage.js
CHANGED
|
@@ -24,4 +24,18 @@ export async function loadEncryption() {
|
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
28
|
+
export async function saveConfig(config) {
|
|
29
|
+
await ensureConfigDir();
|
|
30
|
+
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
31
|
+
}
|
|
32
|
+
export async function loadConfig() {
|
|
33
|
+
try {
|
|
34
|
+
const data = await fs.readFile(CONFIG_FILE, 'utf-8');
|
|
35
|
+
return JSON.parse(data);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
27
41
|
//# sourceMappingURL=storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,IAAI,EAAE,EAAC,MAAM,IAAI,CAAC;AAClC,OAAO,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAC1B,OAAO,EAAC,OAAO,EAAC,MAAM,IAAI,CAAC;AAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAClD,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAM5D,KAAK,UAAU,eAAe;IAC1B,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAClD,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAA4B;IAC7D,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAChC,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,IAAI,EAAE,EAAC,MAAM,IAAI,CAAC;AAClC,OAAO,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAC1B,OAAO,EAAC,OAAO,EAAC,MAAM,IAAI,CAAC;AAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AAClD,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAM5D,KAAK,UAAU,eAAe;IAC1B,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACL,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAClD,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAA4B;IAC7D,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAChC,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAMpD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAoB;IACjD,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC5B,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@commit451/salamander",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Never be AFK",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"salamander": "bin/salamander.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"dev": "tsx src/index.ts",
|
|
13
|
-
"start": "node dist/index.js",
|
|
14
|
-
"prepare": "npm run build",
|
|
15
|
-
"pub": "npm publish --access public"
|
|
16
|
-
},
|
|
17
|
-
"engines": {
|
|
18
|
-
"node": ">=18.0.0"
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@inquirer/prompts": "^7.8.6",
|
|
22
|
-
"chalk": "^5.6.2",
|
|
23
|
-
"commander": "^14.0.1",
|
|
24
|
-
"firebase": "^12.3.0"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"@types/node": "^24.5.2",
|
|
28
|
-
"tsx": "^4.20.5",
|
|
29
|
-
"typescript": "^5.9.2"
|
|
30
|
-
},
|
|
31
|
-
"keywords": [
|
|
32
|
-
"cli",
|
|
33
|
-
"afk",
|
|
34
|
-
"automation",
|
|
35
|
-
"tool"
|
|
36
|
-
],
|
|
37
|
-
"author": "",
|
|
38
|
-
"license": "ISC",
|
|
39
|
-
"repository": {
|
|
40
|
-
"type": "git",
|
|
41
|
-
"url": ""
|
|
42
|
-
},
|
|
43
|
-
"homepage": "",
|
|
44
|
-
"bugs": {
|
|
45
|
-
"url": ""
|
|
46
|
-
},
|
|
47
|
-
"files": [
|
|
48
|
-
"dist/**/*",
|
|
49
|
-
"bin/**/*",
|
|
50
|
-
"README.md"
|
|
51
|
-
]
|
|
52
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@commit451/salamander",
|
|
3
|
+
"version": "1.3.1",
|
|
4
|
+
"description": "Never be AFK",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"salamander": "bin/salamander.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsx src/index.ts",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"prepare": "npm run build",
|
|
15
|
+
"pub": "npm publish --access public"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18.0.0"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@inquirer/prompts": "^7.8.6",
|
|
22
|
+
"chalk": "^5.6.2",
|
|
23
|
+
"commander": "^14.0.1",
|
|
24
|
+
"firebase": "^12.3.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^24.5.2",
|
|
28
|
+
"tsx": "^4.20.5",
|
|
29
|
+
"typescript": "^5.9.2"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"cli",
|
|
33
|
+
"afk",
|
|
34
|
+
"automation",
|
|
35
|
+
"tool"
|
|
36
|
+
],
|
|
37
|
+
"author": "",
|
|
38
|
+
"license": "ISC",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": ""
|
|
42
|
+
},
|
|
43
|
+
"homepage": "",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": ""
|
|
46
|
+
},
|
|
47
|
+
"files": [
|
|
48
|
+
"dist/**/*",
|
|
49
|
+
"bin/**/*",
|
|
50
|
+
"README.md"
|
|
51
|
+
]
|
|
52
|
+
}
|