@firela/billclaw-core 0.1.3
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 +21 -0
- package/README.md +109 -0
- package/dist/billclaw.d.ts +76 -0
- package/dist/billclaw.d.ts.map +1 -0
- package/dist/billclaw.js +205 -0
- package/dist/billclaw.js.map +1 -0
- package/dist/credentials/index.d.ts +8 -0
- package/dist/credentials/index.d.ts.map +1 -0
- package/dist/credentials/index.js +8 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/credentials/keychain.d.ts +92 -0
- package/dist/credentials/keychain.d.ts.map +1 -0
- package/dist/credentials/keychain.js +172 -0
- package/dist/credentials/keychain.js.map +1 -0
- package/dist/credentials/store.d.ts +76 -0
- package/dist/credentials/store.d.ts.map +1 -0
- package/dist/credentials/store.js +144 -0
- package/dist/credentials/store.js.map +1 -0
- package/dist/errors/errors.d.ts +92 -0
- package/dist/errors/errors.d.ts.map +1 -0
- package/dist/errors/errors.js +315 -0
- package/dist/errors/errors.js.map +1 -0
- package/dist/errors/index.d.ts +7 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +7 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/exporters/beancount.d.ts +42 -0
- package/dist/exporters/beancount.d.ts.map +1 -0
- package/dist/exporters/beancount.js +141 -0
- package/dist/exporters/beancount.js.map +1 -0
- package/dist/exporters/index.d.ts +8 -0
- package/dist/exporters/index.d.ts.map +1 -0
- package/dist/exporters/index.js +8 -0
- package/dist/exporters/index.js.map +1 -0
- package/dist/exporters/ledger.d.ts +42 -0
- package/dist/exporters/ledger.d.ts.map +1 -0
- package/dist/exporters/ledger.js +139 -0
- package/dist/exporters/ledger.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/models/config.d.ts +552 -0
- package/dist/models/config.d.ts.map +1 -0
- package/dist/models/config.js +168 -0
- package/dist/models/config.js.map +1 -0
- package/dist/models/index.d.ts +7 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +8 -0
- package/dist/models/index.js.map +1 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +7 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/types.d.ts +110 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +85 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/security/audit.d.ts +148 -0
- package/dist/security/audit.d.ts.map +1 -0
- package/dist/security/audit.js +286 -0
- package/dist/security/audit.js.map +1 -0
- package/dist/security/index.d.ts +7 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +7 -0
- package/dist/security/index.js.map +1 -0
- package/dist/services/event-emitter.d.ts +171 -0
- package/dist/services/event-emitter.d.ts.map +1 -0
- package/dist/services/event-emitter.js +287 -0
- package/dist/services/event-emitter.js.map +1 -0
- package/dist/services/index.d.ts +8 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +8 -0
- package/dist/services/index.js.map +1 -0
- package/dist/sources/gmail/bill-recognizer.d.ts +71 -0
- package/dist/sources/gmail/bill-recognizer.d.ts.map +1 -0
- package/dist/sources/gmail/bill-recognizer.js +341 -0
- package/dist/sources/gmail/bill-recognizer.js.map +1 -0
- package/dist/sources/gmail/email-parser.d.ts +68 -0
- package/dist/sources/gmail/email-parser.d.ts.map +1 -0
- package/dist/sources/gmail/email-parser.js +238 -0
- package/dist/sources/gmail/email-parser.js.map +1 -0
- package/dist/sources/gmail/gmail-fetch.d.ts +54 -0
- package/dist/sources/gmail/gmail-fetch.d.ts.map +1 -0
- package/dist/sources/gmail/gmail-fetch.js +300 -0
- package/dist/sources/gmail/gmail-fetch.js.map +1 -0
- package/dist/sources/gmail/index.d.ts +7 -0
- package/dist/sources/gmail/index.d.ts.map +1 -0
- package/dist/sources/gmail/index.js +7 -0
- package/dist/sources/gmail/index.js.map +1 -0
- package/dist/sources/index.d.ts +8 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +8 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/plaid/index.d.ts +7 -0
- package/dist/sources/plaid/index.d.ts.map +1 -0
- package/dist/sources/plaid/index.js +7 -0
- package/dist/sources/plaid/index.js.map +1 -0
- package/dist/sources/plaid/plaid-sync.d.ts +42 -0
- package/dist/sources/plaid/plaid-sync.d.ts.map +1 -0
- package/dist/sources/plaid/plaid-sync.js +182 -0
- package/dist/sources/plaid/plaid-sync.js.map +1 -0
- package/dist/storage/cache.d.ts +134 -0
- package/dist/storage/cache.d.ts.map +1 -0
- package/dist/storage/cache.js +239 -0
- package/dist/storage/cache.js.map +1 -0
- package/dist/storage/index.d.ts +11 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +11 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/indexes.d.ts +136 -0
- package/dist/storage/indexes.d.ts.map +1 -0
- package/dist/storage/indexes.js +294 -0
- package/dist/storage/indexes.js.map +1 -0
- package/dist/storage/locking.d.ts +103 -0
- package/dist/storage/locking.d.ts.map +1 -0
- package/dist/storage/locking.js +158 -0
- package/dist/storage/locking.js.map +1 -0
- package/dist/storage/streaming.d.ts +102 -0
- package/dist/storage/streaming.d.ts.map +1 -0
- package/dist/storage/streaming.js +245 -0
- package/dist/storage/streaming.js.map +1 -0
- package/dist/storage/transaction-storage.d.ts +101 -0
- package/dist/storage/transaction-storage.d.ts.map +1 -0
- package/dist/storage/transaction-storage.js +193 -0
- package/dist/storage/transaction-storage.js.map +1 -0
- package/dist/sync/index.d.ts +7 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +7 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/sync-service.d.ts +42 -0
- package/dist/sync/sync-service.d.ts.map +1 -0
- package/dist/sync/sync-service.js +112 -0
- package/dist/sync/sync-service.js.map +1 -0
- package/dist/test-fixtures.d.ts +38 -0
- package/dist/test-fixtures.d.ts.map +1 -0
- package/dist/test-fixtures.js +137 -0
- package/dist/test-fixtures.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform keychain credential storage for BillClaw
|
|
3
|
+
*
|
|
4
|
+
* Uses keytar to securely store sensitive tokens in the platform keychain:
|
|
5
|
+
* - macOS: Keychain
|
|
6
|
+
* - Windows: Credential Manager
|
|
7
|
+
* - Linux: Secret Service API / KWallet
|
|
8
|
+
*
|
|
9
|
+
* This provides P0 security for:
|
|
10
|
+
* - Plaid access tokens
|
|
11
|
+
* - Gmail refresh tokens
|
|
12
|
+
* - GoCardless access tokens
|
|
13
|
+
*/
|
|
14
|
+
// Keytar is an optional dependency - will be installed by adapter
|
|
15
|
+
let keytarModule = null;
|
|
16
|
+
/**
|
|
17
|
+
* Initialize keytar module
|
|
18
|
+
* Call this before using keychain functions
|
|
19
|
+
*/
|
|
20
|
+
export async function initKeytar() {
|
|
21
|
+
if (!keytarModule) {
|
|
22
|
+
try {
|
|
23
|
+
keytarModule = await import("keytar");
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw new Error("keytar is not installed. Install it with: npm install keytar");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Service name for BillClaw in keychain
|
|
32
|
+
*/
|
|
33
|
+
const KEYCHAIN_SERVICE = "billclaw";
|
|
34
|
+
/**
|
|
35
|
+
* Store a credential in the platform keychain
|
|
36
|
+
*
|
|
37
|
+
* @param key - Credential identifier (e.g., "plaid_access_token:account123")
|
|
38
|
+
* @param value - Sensitive value to store (e.g., access token)
|
|
39
|
+
* @param logger - Optional logger for audit logging
|
|
40
|
+
*/
|
|
41
|
+
export async function setCredential(key, value, logger) {
|
|
42
|
+
await initKeytar();
|
|
43
|
+
const keytar = keytarModule;
|
|
44
|
+
try {
|
|
45
|
+
await keytar.setPassword(KEYCHAIN_SERVICE, key, value);
|
|
46
|
+
logger?.debug?.(`Stored credential in keychain: ${key}`);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
logger?.error?.(`Failed to store credential in keychain: ${key}`, error);
|
|
50
|
+
throw new Error(`Failed to store credential in keychain: ${error instanceof Error ? error.message : String(error)}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Retrieve a credential from the platform keychain
|
|
55
|
+
*
|
|
56
|
+
* @param key - Credential identifier
|
|
57
|
+
* @param logger - Optional logger for audit logging
|
|
58
|
+
* @returns The credential value, or null if not found
|
|
59
|
+
*/
|
|
60
|
+
export async function getCredential(key, logger) {
|
|
61
|
+
await initKeytar();
|
|
62
|
+
const keytar = keytarModule;
|
|
63
|
+
try {
|
|
64
|
+
const value = await keytar.getPassword(KEYCHAIN_SERVICE, key);
|
|
65
|
+
if (value !== null) {
|
|
66
|
+
logger?.debug?.(`Retrieved credential from keychain: ${key}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
logger?.debug?.(`Credential not found in keychain: ${key}`);
|
|
70
|
+
}
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logger?.error?.(`Failed to retrieve credential from keychain: ${key}`, error);
|
|
75
|
+
throw new Error(`Failed to retrieve credential from keychain: ${error instanceof Error ? error.message : String(error)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Delete a credential from the platform keychain
|
|
80
|
+
*
|
|
81
|
+
* @param key - Credential identifier
|
|
82
|
+
* @param logger - Optional logger for audit logging
|
|
83
|
+
* @returns true if the credential was deleted, false if it didn't exist
|
|
84
|
+
*/
|
|
85
|
+
export async function deleteCredential(key, logger) {
|
|
86
|
+
await initKeytar();
|
|
87
|
+
const keytar = keytarModule;
|
|
88
|
+
try {
|
|
89
|
+
const result = await keytar.deletePassword(KEYCHAIN_SERVICE, key);
|
|
90
|
+
if (result) {
|
|
91
|
+
logger?.debug?.(`Deleted credential from keychain: ${key}`);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
logger?.debug?.(`Credential not found in keychain (could not delete): ${key}`);
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
logger?.error?.(`Failed to delete credential from keychain: ${key}`, error);
|
|
100
|
+
throw new Error(`Failed to delete credential from keychain: ${error instanceof Error ? error.message : String(error)}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check if a credential exists in the keychain
|
|
105
|
+
*
|
|
106
|
+
* @param key - Credential identifier
|
|
107
|
+
* @param logger - Optional logger for audit logging
|
|
108
|
+
* @returns true if the credential exists
|
|
109
|
+
*/
|
|
110
|
+
export async function hasCredential(key, logger) {
|
|
111
|
+
const value = await getCredential(key, logger);
|
|
112
|
+
return value !== null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* List all credential keys for BillClaw
|
|
116
|
+
*
|
|
117
|
+
* Note: keytar doesn't provide a direct way to list all keys,
|
|
118
|
+
* so this returns empty array. Applications should track
|
|
119
|
+
* their own credential keys separately.
|
|
120
|
+
*
|
|
121
|
+
* @returns Empty array (keytar limitation)
|
|
122
|
+
*/
|
|
123
|
+
export async function listCredentialKeys() {
|
|
124
|
+
// keytar doesn't support listing keys
|
|
125
|
+
// Applications should maintain their own registry
|
|
126
|
+
return [];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Clear all BillClaw credentials from the keychain
|
|
130
|
+
*
|
|
131
|
+
* WARNING: This is a destructive operation. Use with caution.
|
|
132
|
+
*
|
|
133
|
+
* @param keys - List of credential keys to delete
|
|
134
|
+
* @param logger - Optional logger for audit logging
|
|
135
|
+
*/
|
|
136
|
+
export async function clearAllCredentials(keys, logger) {
|
|
137
|
+
logger?.warn?.(`Clearing ${keys.length} credentials from keychain`);
|
|
138
|
+
for (const key of keys) {
|
|
139
|
+
await deleteCredential(key, logger);
|
|
140
|
+
}
|
|
141
|
+
logger?.info?.(`Cleared all credentials from keychain`);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Keychain utility functions for building credential keys
|
|
145
|
+
*/
|
|
146
|
+
export const KeychainKeys = {
|
|
147
|
+
/**
|
|
148
|
+
* Build a Plaid access token key
|
|
149
|
+
*/
|
|
150
|
+
plaidAccessToken(accountId) {
|
|
151
|
+
return `plaid_access_token:${accountId}`;
|
|
152
|
+
},
|
|
153
|
+
/**
|
|
154
|
+
* Build a Gmail refresh token key
|
|
155
|
+
*/
|
|
156
|
+
gmailRefreshToken(accountId) {
|
|
157
|
+
return `gmail_refresh_token:${accountId}`;
|
|
158
|
+
},
|
|
159
|
+
/**
|
|
160
|
+
* Build a GoCardless access token key
|
|
161
|
+
*/
|
|
162
|
+
gocardlessAccessToken(accountId) {
|
|
163
|
+
return `gocardless_access_token:${accountId}`;
|
|
164
|
+
},
|
|
165
|
+
/**
|
|
166
|
+
* Build a GoCardless requisition ID key
|
|
167
|
+
*/
|
|
168
|
+
gocardlessRequisitionId(accountId) {
|
|
169
|
+
return `gocardless_requisition_id:${accountId}`;
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
//# sourceMappingURL=keychain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keychain.js","sourceRoot":"","sources":["../../src/credentials/keychain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified credential store interface for BillClaw
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent API for storing and retrieving credentials,
|
|
5
|
+
* with support for both keychain storage (secure) and in-memory
|
|
6
|
+
* fallback for development/testing.
|
|
7
|
+
*/
|
|
8
|
+
import type { Logger } from "../errors/errors.js";
|
|
9
|
+
/**
|
|
10
|
+
* Credential storage strategy
|
|
11
|
+
*/
|
|
12
|
+
export declare enum CredentialStrategy {
|
|
13
|
+
/** Store in platform keychain (recommended for production) */
|
|
14
|
+
KEYCHAIN = "keychain",
|
|
15
|
+
/** Store in memory only (for testing/development, NOT secure) */
|
|
16
|
+
MEMORY = "memory"
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Credential store configuration
|
|
20
|
+
*/
|
|
21
|
+
export interface CredentialStoreConfig {
|
|
22
|
+
strategy: CredentialStrategy;
|
|
23
|
+
logger?: Logger;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Unified credential store
|
|
27
|
+
*/
|
|
28
|
+
export declare class CredentialStore {
|
|
29
|
+
private memoryStore;
|
|
30
|
+
private config;
|
|
31
|
+
constructor(config: CredentialStoreConfig);
|
|
32
|
+
/**
|
|
33
|
+
* Store a credential
|
|
34
|
+
*
|
|
35
|
+
* @param key - Credential identifier
|
|
36
|
+
* @param value - Sensitive value to store
|
|
37
|
+
*/
|
|
38
|
+
set(key: string, value: string): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Retrieve a credential
|
|
41
|
+
*
|
|
42
|
+
* @param key - Credential identifier
|
|
43
|
+
* @returns The credential value, or null if not found
|
|
44
|
+
*/
|
|
45
|
+
get(key: string): Promise<string | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Delete a credential
|
|
48
|
+
*
|
|
49
|
+
* @param key - Credential identifier
|
|
50
|
+
* @returns true if the credential was deleted
|
|
51
|
+
*/
|
|
52
|
+
delete(key: string): Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* Check if a credential exists
|
|
55
|
+
*
|
|
56
|
+
* @param key - Credential identifier
|
|
57
|
+
* @returns true if the credential exists
|
|
58
|
+
*/
|
|
59
|
+
has(key: string): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* List all credential keys
|
|
62
|
+
*
|
|
63
|
+
* @returns Array of credential keys
|
|
64
|
+
*/
|
|
65
|
+
list(): Promise<string[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Clear all credentials
|
|
68
|
+
*/
|
|
69
|
+
clear(): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a credential store with the given configuration
|
|
73
|
+
*/
|
|
74
|
+
export declare function createCredentialStore(config: CredentialStoreConfig): CredentialStore;
|
|
75
|
+
export * from "./keychain.js";
|
|
76
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/credentials/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAGjD;;GAEG;AACH,oBAAY,kBAAkB;IAC5B,8DAA8D;IAC9D,QAAQ,aAAa;IAErB,iEAAiE;IACjE,MAAM,WAAW;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAiCD;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,MAAM,CAAuB;gBAEzB,MAAM,EAAE,qBAAqB;IAKzC;;;;;OAKG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpD;;;;;OAKG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAQ9C;;;;;OAKG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ3C;;;;;OAKG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQxC;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ/B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAS7B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CAEjB;AAGD,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified credential store interface for BillClaw
|
|
3
|
+
*
|
|
4
|
+
* Provides a consistent API for storing and retrieving credentials,
|
|
5
|
+
* with support for both keychain storage (secure) and in-memory
|
|
6
|
+
* fallback for development/testing.
|
|
7
|
+
*/
|
|
8
|
+
import * as keychain from "./keychain.js";
|
|
9
|
+
/**
|
|
10
|
+
* Credential storage strategy
|
|
11
|
+
*/
|
|
12
|
+
export var CredentialStrategy;
|
|
13
|
+
(function (CredentialStrategy) {
|
|
14
|
+
/** Store in platform keychain (recommended for production) */
|
|
15
|
+
CredentialStrategy["KEYCHAIN"] = "keychain";
|
|
16
|
+
/** Store in memory only (for testing/development, NOT secure) */
|
|
17
|
+
CredentialStrategy["MEMORY"] = "memory";
|
|
18
|
+
})(CredentialStrategy || (CredentialStrategy = {}));
|
|
19
|
+
/**
|
|
20
|
+
* In-memory credential storage (NOT secure - for testing only)
|
|
21
|
+
*/
|
|
22
|
+
class MemoryCredentialStore {
|
|
23
|
+
credentials = new Map();
|
|
24
|
+
async set(key, value) {
|
|
25
|
+
this.credentials.set(key, value);
|
|
26
|
+
}
|
|
27
|
+
async get(key) {
|
|
28
|
+
return this.credentials.get(key) || null;
|
|
29
|
+
}
|
|
30
|
+
async delete(key) {
|
|
31
|
+
return this.credentials.delete(key);
|
|
32
|
+
}
|
|
33
|
+
async has(key) {
|
|
34
|
+
return this.credentials.has(key);
|
|
35
|
+
}
|
|
36
|
+
async list() {
|
|
37
|
+
return Array.from(this.credentials.keys());
|
|
38
|
+
}
|
|
39
|
+
async clear() {
|
|
40
|
+
this.credentials.clear();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Unified credential store
|
|
45
|
+
*/
|
|
46
|
+
export class CredentialStore {
|
|
47
|
+
memoryStore;
|
|
48
|
+
config;
|
|
49
|
+
constructor(config) {
|
|
50
|
+
this.config = config;
|
|
51
|
+
this.memoryStore = new MemoryCredentialStore();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Store a credential
|
|
55
|
+
*
|
|
56
|
+
* @param key - Credential identifier
|
|
57
|
+
* @param value - Sensitive value to store
|
|
58
|
+
*/
|
|
59
|
+
async set(key, value) {
|
|
60
|
+
if (this.config.strategy === CredentialStrategy.KEYCHAIN) {
|
|
61
|
+
await keychain.setCredential(key, value, this.config.logger);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
await this.memoryStore.set(key, value);
|
|
65
|
+
this.config.logger?.warn?.(`Stored credential in memory (NOT SECURE): ${key}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Retrieve a credential
|
|
70
|
+
*
|
|
71
|
+
* @param key - Credential identifier
|
|
72
|
+
* @returns The credential value, or null if not found
|
|
73
|
+
*/
|
|
74
|
+
async get(key) {
|
|
75
|
+
if (this.config.strategy === CredentialStrategy.KEYCHAIN) {
|
|
76
|
+
return keychain.getCredential(key, this.config.logger);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
return this.memoryStore.get(key);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Delete a credential
|
|
84
|
+
*
|
|
85
|
+
* @param key - Credential identifier
|
|
86
|
+
* @returns true if the credential was deleted
|
|
87
|
+
*/
|
|
88
|
+
async delete(key) {
|
|
89
|
+
if (this.config.strategy === CredentialStrategy.KEYCHAIN) {
|
|
90
|
+
return keychain.deleteCredential(key, this.config.logger);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return this.memoryStore.delete(key);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if a credential exists
|
|
98
|
+
*
|
|
99
|
+
* @param key - Credential identifier
|
|
100
|
+
* @returns true if the credential exists
|
|
101
|
+
*/
|
|
102
|
+
async has(key) {
|
|
103
|
+
if (this.config.strategy === CredentialStrategy.KEYCHAIN) {
|
|
104
|
+
return keychain.hasCredential(key, this.config.logger);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
return this.memoryStore.has(key);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* List all credential keys
|
|
112
|
+
*
|
|
113
|
+
* @returns Array of credential keys
|
|
114
|
+
*/
|
|
115
|
+
async list() {
|
|
116
|
+
if (this.config.strategy === CredentialStrategy.KEYCHAIN) {
|
|
117
|
+
return keychain.listCredentialKeys();
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
return this.memoryStore.list();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Clear all credentials
|
|
125
|
+
*/
|
|
126
|
+
async clear() {
|
|
127
|
+
const keys = await this.list();
|
|
128
|
+
if (this.config.strategy === CredentialStrategy.KEYCHAIN) {
|
|
129
|
+
await keychain.clearAllCredentials(keys, this.config.logger);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
await this.memoryStore.clear();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Create a credential store with the given configuration
|
|
138
|
+
*/
|
|
139
|
+
export function createCredentialStore(config) {
|
|
140
|
+
return new CredentialStore(config);
|
|
141
|
+
}
|
|
142
|
+
// Re-export keychain utilities for convenience
|
|
143
|
+
export * from "./keychain.js";
|
|
144
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/credentials/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error handling utilities for BillClaw
|
|
3
|
+
*
|
|
4
|
+
* Provides user-friendly error messages, recovery suggestions,
|
|
5
|
+
* and troubleshooting guides.
|
|
6
|
+
*
|
|
7
|
+
* Framework-agnostic: Logger is provided via runtime abstraction.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Error categories for better user messaging
|
|
11
|
+
*/
|
|
12
|
+
export declare enum ErrorCategory {
|
|
13
|
+
CONFIG = "configuration",
|
|
14
|
+
CREDENTIALS = "credentials",
|
|
15
|
+
NETWORK = "network",
|
|
16
|
+
PLAID_API = "plaid_api",
|
|
17
|
+
PLAID_AUTH = "plaid_auth",
|
|
18
|
+
PLAID_ITEM = "plaid_item",
|
|
19
|
+
GMAIL_API = "gmail_api",
|
|
20
|
+
GMAIL_AUTH = "gmail_auth",
|
|
21
|
+
STORAGE = "storage",
|
|
22
|
+
FILE_SYSTEM = "file_system",
|
|
23
|
+
UNKNOWN = "unknown"
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* User-friendly error with recovery suggestions
|
|
27
|
+
*/
|
|
28
|
+
export interface UserError {
|
|
29
|
+
type: "UserError";
|
|
30
|
+
category: ErrorCategory;
|
|
31
|
+
title: string;
|
|
32
|
+
message: string;
|
|
33
|
+
suggestions: string[];
|
|
34
|
+
docsLink?: string;
|
|
35
|
+
error?: Error;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Logger interface for framework-agnostic logging
|
|
39
|
+
*/
|
|
40
|
+
export interface Logger {
|
|
41
|
+
info(...args: unknown[]): void;
|
|
42
|
+
error(...args: unknown[]): void;
|
|
43
|
+
warn(...args: unknown[]): void;
|
|
44
|
+
debug(...args: unknown[]): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create a user-friendly error
|
|
48
|
+
*/
|
|
49
|
+
export declare function createUserError(category: ErrorCategory, title: string, message: string, suggestions: string[], docsLink?: string, originalError?: Error): UserError;
|
|
50
|
+
/**
|
|
51
|
+
* Format error for display to user
|
|
52
|
+
*/
|
|
53
|
+
export declare function formatError(error: UserError): string;
|
|
54
|
+
/**
|
|
55
|
+
* Parse Plaid error codes and create user-friendly errors
|
|
56
|
+
*/
|
|
57
|
+
export declare function parsePlaidError(error: {
|
|
58
|
+
error_code?: string;
|
|
59
|
+
error_message?: string;
|
|
60
|
+
error_type?: string;
|
|
61
|
+
display_message?: string;
|
|
62
|
+
request_id?: string;
|
|
63
|
+
}): UserError;
|
|
64
|
+
/**
|
|
65
|
+
* Parse Gmail API errors and create user-friendly errors
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseGmailError(error: {
|
|
68
|
+
code?: number;
|
|
69
|
+
message?: string;
|
|
70
|
+
status?: number;
|
|
71
|
+
}): UserError;
|
|
72
|
+
/**
|
|
73
|
+
* Parse network errors
|
|
74
|
+
*/
|
|
75
|
+
export declare function parseNetworkError(error: Error): UserError;
|
|
76
|
+
/**
|
|
77
|
+
* Parse file system errors
|
|
78
|
+
*/
|
|
79
|
+
export declare function parseFileSystemError(error: Error, filePath?: string): UserError;
|
|
80
|
+
/**
|
|
81
|
+
* Type guard to check if error is a UserError
|
|
82
|
+
*/
|
|
83
|
+
export declare function isUserError(error: unknown): error is UserError;
|
|
84
|
+
/**
|
|
85
|
+
* Log error with context for debugging
|
|
86
|
+
*/
|
|
87
|
+
export declare function logError(logger: Logger | undefined, error: UserError | Error, context?: Record<string, unknown>): void;
|
|
88
|
+
/**
|
|
89
|
+
* Get troubleshooting guide URL for error category
|
|
90
|
+
*/
|
|
91
|
+
export declare function getTroubleshootingUrl(category: ErrorCategory): string;
|
|
92
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,oBAAY,aAAa;IAEvB,MAAM,kBAAkB;IACxB,WAAW,gBAAgB;IAC3B,OAAO,YAAY;IAGnB,SAAS,cAAc;IACvB,UAAU,eAAe;IACzB,UAAU,eAAe;IAGzB,SAAS,cAAc;IACvB,UAAU,eAAe;IAGzB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAG3B,OAAO,YAAY;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,aAAa,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;IAC9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;CAChC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,EACrB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,KAAK,GACpB,SAAS,CAUX;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CA2BpD;AAsBD;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,SAAS,CA8GZ;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,SAAS,CA4EZ;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,CAiEzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB,SAAS,CA0DX;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAO9D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CACtB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,KAAK,EAAE,SAAS,GAAG,KAAK,EACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,IAAI,CAiBN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAiBrE"}
|