@zeph-to/cli 1.12.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/LICENSE +190 -0
- package/README.md +499 -0
- package/dist/agents.d.ts +8 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +29 -0
- package/dist/check-update.d.ts +4 -0
- package/dist/check-update.d.ts.map +1 -0
- package/dist/check-update.js +80 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +374 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +36 -0
- package/dist/crypto.d.ts +82 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +291 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +28 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/installer.d.ts +14 -0
- package/dist/installer.d.ts.map +1 -0
- package/dist/installer.js +464 -0
- package/dist/listener.d.ts +126 -0
- package/dist/listener.d.ts.map +1 -0
- package/dist/listener.js +1008 -0
- package/dist/login.d.ts +38 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/login.js +182 -0
- package/dist/templates.d.ts +44 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +257 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/uninstall.d.ts +2 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/uninstall.js +217 -0
- package/dist/verify.d.ts +2 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +109 -0
- package/dist/wrapper.d.ts +26 -0
- package/dist/wrapper.d.ts.map +1 -0
- package/dist/wrapper.js +238 -0
- package/dist/zeph-hook.d.ts +23 -0
- package/dist/zeph-hook.d.ts.map +1 -0
- package/dist/zeph-hook.js +196 -0
- package/package.json +75 -0
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Device-shared encryption for Hook SDK — self-contained ECDH P-256 +
|
|
4
|
+
* AES-256-GCM. Mirrors @zeph/crypto API but bundled inline (no external
|
|
5
|
+
* dependency). Uses Web Crypto API (globalThis.crypto.subtle) — Node.js 18+.
|
|
6
|
+
*
|
|
7
|
+
* Threat model honesty (do not call this "E2E" without a footnote):
|
|
8
|
+
*
|
|
9
|
+
* The Zeph backend persists the per-user private key in plaintext so it
|
|
10
|
+
* can be synced down to a fresh device (fetchServerKeys / uploadServerKeys
|
|
11
|
+
* below). That means the backend can decrypt any push body — this is NOT
|
|
12
|
+
* end-to-end in the standard sense. What it gives you is:
|
|
13
|
+
* • Protection against passive network observers
|
|
14
|
+
* • Protection against a leaked DB snapshot taken without the key store
|
|
15
|
+
* • Cross-device readability (all your devices share one keypair)
|
|
16
|
+
* What it does NOT give you:
|
|
17
|
+
* • Protection against the Zeph backend itself
|
|
18
|
+
* • Forward secrecy — encryptPushBodyForSelf / encryptFileForSelf do
|
|
19
|
+
* ECDH(self, self), which collapses to a static derived key. A single
|
|
20
|
+
* device compromise (since all your devices share the same keypair)
|
|
21
|
+
* lets the attacker decrypt every past push for which they have the
|
|
22
|
+
* ciphertext. The per-message AES key is random, but its wrap key is
|
|
23
|
+
* static, so wrapped keys are decryptable forever.
|
|
24
|
+
*
|
|
25
|
+
* True E2E would require a per-device keypair (server stores only public
|
|
26
|
+
* keys; senders wrap the message key once per recipient device public
|
|
27
|
+
* key). That refactor is on the roadmap; until then, treat push bodies as
|
|
28
|
+
* sensitive-but-not-secret.
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.encryptFileForSelf = exports.encryptFileForRecipient = exports.encryptPushBodyForSelf = exports.encryptPushBody = exports.getPublicKey = exports.getKeyPair = exports.initCrypto = void 0;
|
|
32
|
+
/// <reference lib="dom" />
|
|
33
|
+
const fs_1 = require("fs");
|
|
34
|
+
const os_1 = require("os");
|
|
35
|
+
const path_1 = require("path");
|
|
36
|
+
// ─── Base64 helpers ───
|
|
37
|
+
const toBase64 = (buffer) => {
|
|
38
|
+
const bytes = new Uint8Array(buffer);
|
|
39
|
+
let binary = '';
|
|
40
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
41
|
+
binary += String.fromCharCode(bytes[i]);
|
|
42
|
+
}
|
|
43
|
+
return btoa(binary);
|
|
44
|
+
};
|
|
45
|
+
const fromBase64 = (base64) => {
|
|
46
|
+
const binary = atob(base64);
|
|
47
|
+
const bytes = new Uint8Array(binary.length);
|
|
48
|
+
for (let i = 0; i < binary.length; i++) {
|
|
49
|
+
bytes[i] = binary.charCodeAt(i);
|
|
50
|
+
}
|
|
51
|
+
return bytes.buffer;
|
|
52
|
+
};
|
|
53
|
+
// ─── ECDH key management ───
|
|
54
|
+
const ECDH_PARAMS = { name: 'ECDH', namedCurve: 'P-256' };
|
|
55
|
+
const generateKeyPair = async () => crypto.subtle.generateKey(ECDH_PARAMS, true, ['deriveKey', 'deriveBits']);
|
|
56
|
+
const exportKeyPair = async (keyPair) => {
|
|
57
|
+
const [publicRaw, privateRaw] = await Promise.all([
|
|
58
|
+
crypto.subtle.exportKey('spki', keyPair.publicKey),
|
|
59
|
+
crypto.subtle.exportKey('pkcs8', keyPair.privateKey),
|
|
60
|
+
]);
|
|
61
|
+
return { publicKey: toBase64(publicRaw), privateKey: toBase64(privateRaw) };
|
|
62
|
+
};
|
|
63
|
+
const importPublicKey = async (base64) => crypto.subtle.importKey('spki', fromBase64(base64), ECDH_PARAMS, true, []);
|
|
64
|
+
const importPrivateKey = async (base64) => crypto.subtle.importKey('pkcs8', fromBase64(base64), ECDH_PARAMS, true, ['deriveKey', 'deriveBits']);
|
|
65
|
+
const importKeyPair = async (exported) => {
|
|
66
|
+
const [publicKey, privateKey] = await Promise.all([
|
|
67
|
+
importPublicKey(exported.publicKey),
|
|
68
|
+
importPrivateKey(exported.privateKey),
|
|
69
|
+
]);
|
|
70
|
+
return { publicKey, privateKey };
|
|
71
|
+
};
|
|
72
|
+
const deriveAesKey = async (privateKey, publicKey) => crypto.subtle.deriveKey({ name: 'ECDH', public: publicKey }, privateKey, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
|
|
73
|
+
const encrypt = async (plaintext, senderPrivateKey, recipientPublicKey) => {
|
|
74
|
+
const messageKey = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']);
|
|
75
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
76
|
+
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, messageKey, new TextEncoder().encode(plaintext));
|
|
77
|
+
const sharedKey = await deriveAesKey(senderPrivateKey, recipientPublicKey);
|
|
78
|
+
const rawMessageKey = await crypto.subtle.exportKey('raw', messageKey);
|
|
79
|
+
const keyIv = crypto.getRandomValues(new Uint8Array(12));
|
|
80
|
+
const encryptedKey = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: keyIv }, sharedKey, rawMessageKey);
|
|
81
|
+
return {
|
|
82
|
+
ciphertext: toBase64(ciphertext),
|
|
83
|
+
iv: toBase64(iv.buffer),
|
|
84
|
+
encryptedKey: toBase64(encryptedKey),
|
|
85
|
+
keyIv: toBase64(keyIv.buffer),
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
// ─── File encryption ───
|
|
89
|
+
const encryptFileContent = async (content, senderPrivateKey, recipientPublicKey) => {
|
|
90
|
+
const buffer = new TextEncoder().encode(content).buffer;
|
|
91
|
+
const fileKey = await crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']);
|
|
92
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
93
|
+
const ciphertext = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, fileKey, buffer);
|
|
94
|
+
const sharedKey = await deriveAesKey(senderPrivateKey, recipientPublicKey);
|
|
95
|
+
const rawFileKey = await crypto.subtle.exportKey('raw', fileKey);
|
|
96
|
+
const keyIv = crypto.getRandomValues(new Uint8Array(12));
|
|
97
|
+
const encryptedKey = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: keyIv }, sharedKey, rawFileKey);
|
|
98
|
+
return {
|
|
99
|
+
ciphertext: Buffer.from(ciphertext),
|
|
100
|
+
iv: toBase64(iv.buffer),
|
|
101
|
+
encryptedKey: toBase64(encryptedKey),
|
|
102
|
+
keyIv: toBase64(keyIv.buffer),
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
// ─── Key persistence (~/.config/zeph/keys.json) ───
|
|
106
|
+
const KEYS_DIR = (0, path_1.join)((0, os_1.homedir)(), '.config', 'zeph');
|
|
107
|
+
const KEYS_PATH = (0, path_1.join)(KEYS_DIR, 'keys.json');
|
|
108
|
+
const loadStoredKeys = () => {
|
|
109
|
+
try {
|
|
110
|
+
return JSON.parse((0, fs_1.readFileSync)(KEYS_PATH, 'utf-8'));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const storeKeys = (exported) => {
|
|
117
|
+
(0, fs_1.mkdirSync)(KEYS_DIR, { recursive: true, mode: 0o700 });
|
|
118
|
+
(0, fs_1.writeFileSync)(KEYS_PATH, JSON.stringify(exported, null, 2), { mode: 0o600 });
|
|
119
|
+
};
|
|
120
|
+
// ─── Cached state ───
|
|
121
|
+
let cachedKeyPair = null;
|
|
122
|
+
let cachedExportedPublicKey = null;
|
|
123
|
+
let cachedOwnPublicKey = null;
|
|
124
|
+
let initPromise = null;
|
|
125
|
+
/**
|
|
126
|
+
* Initialize crypto: sync keys with server, then fallback to local/generate.
|
|
127
|
+
* Server is source of truth for per-user key pair.
|
|
128
|
+
* Safe to call concurrently — deduplicates to single init.
|
|
129
|
+
* Returns the exported public key (Base64 SPKI).
|
|
130
|
+
*/
|
|
131
|
+
const initCrypto = (apiKey, baseUrl) => {
|
|
132
|
+
if (initPromise)
|
|
133
|
+
return initPromise;
|
|
134
|
+
initPromise = (async () => {
|
|
135
|
+
// Try local cache first
|
|
136
|
+
const stored = loadStoredKeys();
|
|
137
|
+
// Try server sync if API key available
|
|
138
|
+
if (apiKey) {
|
|
139
|
+
const serverResult = await fetchServerKeys(apiKey, baseUrl);
|
|
140
|
+
// Server says encryption disabled — skip crypto init
|
|
141
|
+
if (serverResult && !serverResult.encryptionEnabled) {
|
|
142
|
+
cachedKeyPair = null;
|
|
143
|
+
cachedExportedPublicKey = null;
|
|
144
|
+
cachedOwnPublicKey = null;
|
|
145
|
+
return '';
|
|
146
|
+
}
|
|
147
|
+
if (serverResult?.keys) {
|
|
148
|
+
// Server has keys — adopt them (server is source of truth)
|
|
149
|
+
if (!stored || stored.publicKey !== serverResult.keys.publicKey) {
|
|
150
|
+
storeKeys(serverResult.keys);
|
|
151
|
+
}
|
|
152
|
+
cachedKeyPair = await importKeyPair(serverResult.keys);
|
|
153
|
+
cachedExportedPublicKey = serverResult.keys.publicKey;
|
|
154
|
+
cachedOwnPublicKey = cachedKeyPair.publicKey;
|
|
155
|
+
return serverResult.keys.publicKey;
|
|
156
|
+
}
|
|
157
|
+
// Server has no keys
|
|
158
|
+
if (stored) {
|
|
159
|
+
// Upload local keys to server
|
|
160
|
+
await uploadServerKeys(stored, apiKey, baseUrl);
|
|
161
|
+
cachedKeyPair = await importKeyPair(stored);
|
|
162
|
+
cachedExportedPublicKey = stored.publicKey;
|
|
163
|
+
cachedOwnPublicKey = cachedKeyPair.publicKey;
|
|
164
|
+
return stored.publicKey;
|
|
165
|
+
}
|
|
166
|
+
// No keys anywhere — generate + upload
|
|
167
|
+
const keyPair = await generateKeyPair();
|
|
168
|
+
const exported = await exportKeyPair(keyPair);
|
|
169
|
+
storeKeys(exported);
|
|
170
|
+
await uploadServerKeys(exported, apiKey, baseUrl);
|
|
171
|
+
cachedKeyPair = keyPair;
|
|
172
|
+
cachedExportedPublicKey = exported.publicKey;
|
|
173
|
+
cachedOwnPublicKey = keyPair.publicKey;
|
|
174
|
+
return exported.publicKey;
|
|
175
|
+
}
|
|
176
|
+
// No API key — local-only mode
|
|
177
|
+
if (stored) {
|
|
178
|
+
cachedKeyPair = await importKeyPair(stored);
|
|
179
|
+
cachedExportedPublicKey = stored.publicKey;
|
|
180
|
+
cachedOwnPublicKey = cachedKeyPair.publicKey;
|
|
181
|
+
return stored.publicKey;
|
|
182
|
+
}
|
|
183
|
+
const keyPair = await generateKeyPair();
|
|
184
|
+
const exported = await exportKeyPair(keyPair);
|
|
185
|
+
storeKeys(exported);
|
|
186
|
+
cachedKeyPair = keyPair;
|
|
187
|
+
cachedExportedPublicKey = exported.publicKey;
|
|
188
|
+
cachedOwnPublicKey = keyPair.publicKey;
|
|
189
|
+
return exported.publicKey;
|
|
190
|
+
})().catch((err) => {
|
|
191
|
+
initPromise = null;
|
|
192
|
+
throw err;
|
|
193
|
+
});
|
|
194
|
+
return initPromise;
|
|
195
|
+
};
|
|
196
|
+
exports.initCrypto = initCrypto;
|
|
197
|
+
const fetchServerKeys = async (apiKey, baseUrl) => {
|
|
198
|
+
try {
|
|
199
|
+
const url = `${(baseUrl ?? 'https://api.zeph.to/v1').replace(/\/$/, '')}/users/me/keys`;
|
|
200
|
+
const res = await fetch(url, { headers: { 'X-API-Key': apiKey } });
|
|
201
|
+
if (!res.ok)
|
|
202
|
+
return null;
|
|
203
|
+
const json = await res.json();
|
|
204
|
+
const keys = json.data?.encryptionKeys;
|
|
205
|
+
const encryptionEnabled = json.data?.encryptionEnabled ?? (keys ? true : false);
|
|
206
|
+
return {
|
|
207
|
+
keys: keys?.publicKey && keys?.privateKey ? keys : null,
|
|
208
|
+
encryptionEnabled,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const uploadServerKeys = async (keys, apiKey, baseUrl) => {
|
|
216
|
+
try {
|
|
217
|
+
const url = `${(baseUrl ?? 'https://api.zeph.to/v1').replace(/\/$/, '')}/users/me/keys`;
|
|
218
|
+
await fetch(url, {
|
|
219
|
+
method: 'PUT',
|
|
220
|
+
headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
|
|
221
|
+
body: JSON.stringify(keys),
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch { /* non-critical */ }
|
|
225
|
+
};
|
|
226
|
+
const getKeyPair = () => cachedKeyPair;
|
|
227
|
+
exports.getKeyPair = getKeyPair;
|
|
228
|
+
const getPublicKey = () => cachedExportedPublicKey;
|
|
229
|
+
exports.getPublicKey = getPublicKey;
|
|
230
|
+
/**
|
|
231
|
+
* Encrypt push body for a recipient.
|
|
232
|
+
* Returns fields ready to merge into the sendPush payload.
|
|
233
|
+
*/
|
|
234
|
+
const encryptPushBody = async (input, recipientPublicKeyRaw) => {
|
|
235
|
+
if (!cachedKeyPair || !cachedExportedPublicKey)
|
|
236
|
+
throw new Error('Crypto not initialized');
|
|
237
|
+
const recipientKey = await importPublicKey(recipientPublicKeyRaw);
|
|
238
|
+
const payload = await encrypt(JSON.stringify({ title: input.title, body: input.body, url: input.url }), cachedKeyPair.privateKey, recipientKey);
|
|
239
|
+
return {
|
|
240
|
+
body: JSON.stringify({ ciphertext: payload.ciphertext, iv: payload.iv }),
|
|
241
|
+
encryptedKey: JSON.stringify({ encryptedKey: payload.encryptedKey, keyIv: payload.keyIv }),
|
|
242
|
+
senderPublicKey: cachedExportedPublicKey,
|
|
243
|
+
isEncrypted: true,
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
exports.encryptPushBody = encryptPushBody;
|
|
247
|
+
/**
|
|
248
|
+
* Encrypt push body for self (all own devices).
|
|
249
|
+
*/
|
|
250
|
+
const encryptPushBodyForSelf = async (input) => {
|
|
251
|
+
if (!cachedKeyPair || !cachedExportedPublicKey || !cachedOwnPublicKey)
|
|
252
|
+
throw new Error('Crypto not initialized');
|
|
253
|
+
const payload = await encrypt(JSON.stringify({ title: input.title, body: input.body, url: input.url }), cachedKeyPair.privateKey, cachedOwnPublicKey);
|
|
254
|
+
return {
|
|
255
|
+
body: JSON.stringify({ ciphertext: payload.ciphertext, iv: payload.iv }),
|
|
256
|
+
encryptedKey: JSON.stringify({ encryptedKey: payload.encryptedKey, keyIv: payload.keyIv }),
|
|
257
|
+
senderPublicKey: cachedExportedPublicKey,
|
|
258
|
+
isEncrypted: true,
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
exports.encryptPushBodyForSelf = encryptPushBodyForSelf;
|
|
262
|
+
/**
|
|
263
|
+
* Encrypt file content for a recipient.
|
|
264
|
+
* Returns encrypted buffer + key material for file attachment metadata.
|
|
265
|
+
*/
|
|
266
|
+
const encryptFileForRecipient = async (content, recipientPublicKeyRaw) => {
|
|
267
|
+
if (!cachedKeyPair)
|
|
268
|
+
throw new Error('Crypto not initialized');
|
|
269
|
+
const recipientKey = await importPublicKey(recipientPublicKeyRaw);
|
|
270
|
+
const result = await encryptFileContent(content, cachedKeyPair.privateKey, recipientKey);
|
|
271
|
+
return {
|
|
272
|
+
ciphertext: result.ciphertext,
|
|
273
|
+
iv: result.iv,
|
|
274
|
+
encryptedKey: JSON.stringify({ encryptedKey: result.encryptedKey, keyIv: result.keyIv }),
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
exports.encryptFileForRecipient = encryptFileForRecipient;
|
|
278
|
+
/**
|
|
279
|
+
* Encrypt file content for self (all own devices).
|
|
280
|
+
*/
|
|
281
|
+
const encryptFileForSelf = async (content) => {
|
|
282
|
+
if (!cachedKeyPair || !cachedOwnPublicKey)
|
|
283
|
+
throw new Error('Crypto not initialized');
|
|
284
|
+
const result = await encryptFileContent(content, cachedKeyPair.privateKey, cachedOwnPublicKey);
|
|
285
|
+
return {
|
|
286
|
+
ciphertext: result.ciphertext,
|
|
287
|
+
iv: result.iv,
|
|
288
|
+
encryptedKey: JSON.stringify({ encryptedKey: result.encryptedKey, keyIv: result.keyIv }),
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
exports.encryptFileForSelf = encryptFileForSelf;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class ZephError extends Error {
|
|
2
|
+
code: string;
|
|
3
|
+
status: number;
|
|
4
|
+
constructor(message: string, code: string, status: number);
|
|
5
|
+
}
|
|
6
|
+
export declare class AuthenticationError extends ZephError {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
export declare class QuotaExceededError extends ZephError {
|
|
10
|
+
constructor(message?: string);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAM1D;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,SAA0B;CAI9C;AAED,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,OAAO,SAAmB;CAIvC"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuotaExceededError = exports.AuthenticationError = exports.ZephError = void 0;
|
|
4
|
+
class ZephError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
status;
|
|
7
|
+
constructor(message, code, status) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'ZephError';
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.status = status;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.ZephError = ZephError;
|
|
15
|
+
class AuthenticationError extends ZephError {
|
|
16
|
+
constructor(message = 'Authentication failed') {
|
|
17
|
+
super(message, 'AUTHENTICATION_ERROR', 401);
|
|
18
|
+
this.name = 'AuthenticationError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.AuthenticationError = AuthenticationError;
|
|
22
|
+
class QuotaExceededError extends ZephError {
|
|
23
|
+
constructor(message = 'Quota exceeded') {
|
|
24
|
+
super(message, 'QUOTA_EXCEEDED', 403);
|
|
25
|
+
this.name = 'QuotaExceededError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.QuotaExceededError = QuotaExceededError;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ZephHook } from './zeph-hook.js';
|
|
2
|
+
export { ZephError, AuthenticationError, QuotaExceededError } from './errors.js';
|
|
3
|
+
export type { ZephOptions, NotifyPayload, NotifyResult, ListParams, ListResult, DismissOneResult, DismissAllResult, PushItem } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjF,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QuotaExceededError = exports.AuthenticationError = exports.ZephError = exports.ZephHook = void 0;
|
|
4
|
+
var zeph_hook_js_1 = require("./zeph-hook.js");
|
|
5
|
+
Object.defineProperty(exports, "ZephHook", { enumerable: true, get: function () { return zeph_hook_js_1.ZephHook; } });
|
|
6
|
+
var errors_js_1 = require("./errors.js");
|
|
7
|
+
Object.defineProperty(exports, "ZephError", { enumerable: true, get: function () { return errors_js_1.ZephError; } });
|
|
8
|
+
Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_js_1.AuthenticationError; } });
|
|
9
|
+
Object.defineProperty(exports, "QuotaExceededError", { enumerable: true, get: function () { return errors_js_1.QuotaExceededError; } });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Agent } from './agents.js';
|
|
2
|
+
/**
|
|
3
|
+
* True when install should auto-open browser login (ADR 0002): interactive
|
|
4
|
+
* context with no existing credential (--key/env/config all absent).
|
|
5
|
+
*/
|
|
6
|
+
export declare const shouldTriggerLogin: (nonInteractive: boolean, currentKey: string | undefined) => boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Resolve agents from a non-interactive `--only cursor,gemini` flag.
|
|
9
|
+
* Matches on agent id; unknown ids are silently dropped. Exported for
|
|
10
|
+
* unit testing.
|
|
11
|
+
*/
|
|
12
|
+
export declare const filterAgentsByIds: (detected: Agent[], only: string) => Agent[];
|
|
13
|
+
export declare const handleInstall: (args: Record<string, string | boolean>) => Promise<number>;
|
|
14
|
+
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA2BzC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,gBAAgB,OAAO,EAAE,YAAY,MAAM,GAAG,SAAS,KAAG,OAC7D,CAAC;AA+QjC;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,KAAK,EAAE,EAAE,MAAM,MAAM,KAAG,KAAK,EAKxE,CAAC;AA4FF,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAkG1F,CAAC"}
|