@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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/dist/billclaw.d.ts +76 -0
  4. package/dist/billclaw.d.ts.map +1 -0
  5. package/dist/billclaw.js +205 -0
  6. package/dist/billclaw.js.map +1 -0
  7. package/dist/credentials/index.d.ts +8 -0
  8. package/dist/credentials/index.d.ts.map +1 -0
  9. package/dist/credentials/index.js +8 -0
  10. package/dist/credentials/index.js.map +1 -0
  11. package/dist/credentials/keychain.d.ts +92 -0
  12. package/dist/credentials/keychain.d.ts.map +1 -0
  13. package/dist/credentials/keychain.js +172 -0
  14. package/dist/credentials/keychain.js.map +1 -0
  15. package/dist/credentials/store.d.ts +76 -0
  16. package/dist/credentials/store.d.ts.map +1 -0
  17. package/dist/credentials/store.js +144 -0
  18. package/dist/credentials/store.js.map +1 -0
  19. package/dist/errors/errors.d.ts +92 -0
  20. package/dist/errors/errors.d.ts.map +1 -0
  21. package/dist/errors/errors.js +315 -0
  22. package/dist/errors/errors.js.map +1 -0
  23. package/dist/errors/index.d.ts +7 -0
  24. package/dist/errors/index.d.ts.map +1 -0
  25. package/dist/errors/index.js +7 -0
  26. package/dist/errors/index.js.map +1 -0
  27. package/dist/exporters/beancount.d.ts +42 -0
  28. package/dist/exporters/beancount.d.ts.map +1 -0
  29. package/dist/exporters/beancount.js +141 -0
  30. package/dist/exporters/beancount.js.map +1 -0
  31. package/dist/exporters/index.d.ts +8 -0
  32. package/dist/exporters/index.d.ts.map +1 -0
  33. package/dist/exporters/index.js +8 -0
  34. package/dist/exporters/index.js.map +1 -0
  35. package/dist/exporters/ledger.d.ts +42 -0
  36. package/dist/exporters/ledger.d.ts.map +1 -0
  37. package/dist/exporters/ledger.js +139 -0
  38. package/dist/exporters/ledger.js.map +1 -0
  39. package/dist/index.d.ts +23 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +34 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/models/config.d.ts +552 -0
  44. package/dist/models/config.d.ts.map +1 -0
  45. package/dist/models/config.js +168 -0
  46. package/dist/models/config.js.map +1 -0
  47. package/dist/models/index.d.ts +7 -0
  48. package/dist/models/index.d.ts.map +1 -0
  49. package/dist/models/index.js +8 -0
  50. package/dist/models/index.js.map +1 -0
  51. package/dist/runtime/index.d.ts +7 -0
  52. package/dist/runtime/index.d.ts.map +1 -0
  53. package/dist/runtime/index.js +7 -0
  54. package/dist/runtime/index.js.map +1 -0
  55. package/dist/runtime/types.d.ts +110 -0
  56. package/dist/runtime/types.d.ts.map +1 -0
  57. package/dist/runtime/types.js +85 -0
  58. package/dist/runtime/types.js.map +1 -0
  59. package/dist/security/audit.d.ts +148 -0
  60. package/dist/security/audit.d.ts.map +1 -0
  61. package/dist/security/audit.js +286 -0
  62. package/dist/security/audit.js.map +1 -0
  63. package/dist/security/index.d.ts +7 -0
  64. package/dist/security/index.d.ts.map +1 -0
  65. package/dist/security/index.js +7 -0
  66. package/dist/security/index.js.map +1 -0
  67. package/dist/services/event-emitter.d.ts +171 -0
  68. package/dist/services/event-emitter.d.ts.map +1 -0
  69. package/dist/services/event-emitter.js +287 -0
  70. package/dist/services/event-emitter.js.map +1 -0
  71. package/dist/services/index.d.ts +8 -0
  72. package/dist/services/index.d.ts.map +1 -0
  73. package/dist/services/index.js +8 -0
  74. package/dist/services/index.js.map +1 -0
  75. package/dist/sources/gmail/bill-recognizer.d.ts +71 -0
  76. package/dist/sources/gmail/bill-recognizer.d.ts.map +1 -0
  77. package/dist/sources/gmail/bill-recognizer.js +341 -0
  78. package/dist/sources/gmail/bill-recognizer.js.map +1 -0
  79. package/dist/sources/gmail/email-parser.d.ts +68 -0
  80. package/dist/sources/gmail/email-parser.d.ts.map +1 -0
  81. package/dist/sources/gmail/email-parser.js +238 -0
  82. package/dist/sources/gmail/email-parser.js.map +1 -0
  83. package/dist/sources/gmail/gmail-fetch.d.ts +54 -0
  84. package/dist/sources/gmail/gmail-fetch.d.ts.map +1 -0
  85. package/dist/sources/gmail/gmail-fetch.js +300 -0
  86. package/dist/sources/gmail/gmail-fetch.js.map +1 -0
  87. package/dist/sources/gmail/index.d.ts +7 -0
  88. package/dist/sources/gmail/index.d.ts.map +1 -0
  89. package/dist/sources/gmail/index.js +7 -0
  90. package/dist/sources/gmail/index.js.map +1 -0
  91. package/dist/sources/index.d.ts +8 -0
  92. package/dist/sources/index.d.ts.map +1 -0
  93. package/dist/sources/index.js +8 -0
  94. package/dist/sources/index.js.map +1 -0
  95. package/dist/sources/plaid/index.d.ts +7 -0
  96. package/dist/sources/plaid/index.d.ts.map +1 -0
  97. package/dist/sources/plaid/index.js +7 -0
  98. package/dist/sources/plaid/index.js.map +1 -0
  99. package/dist/sources/plaid/plaid-sync.d.ts +42 -0
  100. package/dist/sources/plaid/plaid-sync.d.ts.map +1 -0
  101. package/dist/sources/plaid/plaid-sync.js +182 -0
  102. package/dist/sources/plaid/plaid-sync.js.map +1 -0
  103. package/dist/storage/cache.d.ts +134 -0
  104. package/dist/storage/cache.d.ts.map +1 -0
  105. package/dist/storage/cache.js +239 -0
  106. package/dist/storage/cache.js.map +1 -0
  107. package/dist/storage/index.d.ts +11 -0
  108. package/dist/storage/index.d.ts.map +1 -0
  109. package/dist/storage/index.js +11 -0
  110. package/dist/storage/index.js.map +1 -0
  111. package/dist/storage/indexes.d.ts +136 -0
  112. package/dist/storage/indexes.d.ts.map +1 -0
  113. package/dist/storage/indexes.js +294 -0
  114. package/dist/storage/indexes.js.map +1 -0
  115. package/dist/storage/locking.d.ts +103 -0
  116. package/dist/storage/locking.d.ts.map +1 -0
  117. package/dist/storage/locking.js +158 -0
  118. package/dist/storage/locking.js.map +1 -0
  119. package/dist/storage/streaming.d.ts +102 -0
  120. package/dist/storage/streaming.d.ts.map +1 -0
  121. package/dist/storage/streaming.js +245 -0
  122. package/dist/storage/streaming.js.map +1 -0
  123. package/dist/storage/transaction-storage.d.ts +101 -0
  124. package/dist/storage/transaction-storage.d.ts.map +1 -0
  125. package/dist/storage/transaction-storage.js +193 -0
  126. package/dist/storage/transaction-storage.js.map +1 -0
  127. package/dist/sync/index.d.ts +7 -0
  128. package/dist/sync/index.d.ts.map +1 -0
  129. package/dist/sync/index.js +7 -0
  130. package/dist/sync/index.js.map +1 -0
  131. package/dist/sync/sync-service.d.ts +42 -0
  132. package/dist/sync/sync-service.d.ts.map +1 -0
  133. package/dist/sync/sync-service.js +112 -0
  134. package/dist/sync/sync-service.js.map +1 -0
  135. package/dist/test-fixtures.d.ts +38 -0
  136. package/dist/test-fixtures.d.ts.map +1 -0
  137. package/dist/test-fixtures.js +137 -0
  138. package/dist/test-fixtures.js.map +1 -0
  139. 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"}