@profullstack/coinpay 0.9.0 → 0.11.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/CHANGELOG.md +57 -0
- package/README.md +8 -0
- package/bin/coinpay.js +158 -13
- package/package.json +15 -2
- package/src/client.d.ts +10 -0
- package/src/client.js +91 -0
- package/src/finances-commands.js +613 -0
- package/src/finances-report.js +458 -0
- package/src/finances-reports.d.ts +359 -0
- package/src/finances-reports.js +356 -0
- package/src/finances-tui.js +14 -0
- package/src/finances.d.ts +32 -0
- package/src/finances.js +68 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -0
- package/src/pdf.js +151 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import type { CoinPayClient } from './client.js';
|
|
2
|
+
|
|
3
|
+
export type ProviderCoverage = 'unknown' | 'partial' | 'available_window_fetched';
|
|
4
|
+
export type ReconciliationStatus = 'not_attempted' | 'unavailable' | 'mismatch' | 'user_reconciled';
|
|
5
|
+
export type ReportFormat = 'pdf' | 'html' | 'csv' | 'json';
|
|
6
|
+
export type ReportStatus = 'queued' | 'generating' | 'ready' | 'failed' | 'superseded' | 'deleted';
|
|
7
|
+
export type JobStatus = 'queued' | 'running' | 'waiting_for_budget' | 'partial' | 'failed' | 'completed' | 'cancelled';
|
|
8
|
+
export type JobKind = 'backfill' | 'refresh' | 'scheduled_sync' | 'report' | 'categorize' | 'email_report';
|
|
9
|
+
|
|
10
|
+
/** Thrown by every call here when the server answers with its structured error body. */
|
|
11
|
+
export interface FinanceApiError extends Error {
|
|
12
|
+
code?: string;
|
|
13
|
+
status?: number;
|
|
14
|
+
retryable?: boolean;
|
|
15
|
+
jobId?: string;
|
|
16
|
+
reportId?: string;
|
|
17
|
+
retryAfter?: string | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface FinanceJob {
|
|
21
|
+
id: string;
|
|
22
|
+
kind: JobKind;
|
|
23
|
+
connectionId: string | null;
|
|
24
|
+
status: JobStatus;
|
|
25
|
+
params: Record<string, unknown>;
|
|
26
|
+
progress: Record<string, unknown>;
|
|
27
|
+
result: Record<string, unknown> | null;
|
|
28
|
+
errorCode: string | null;
|
|
29
|
+
errorMessage: string | null;
|
|
30
|
+
attempts: number;
|
|
31
|
+
nextAttemptAt: string | null;
|
|
32
|
+
cancelRequested: boolean;
|
|
33
|
+
createdAt: string;
|
|
34
|
+
startedAt: string | null;
|
|
35
|
+
finishedAt: string | null;
|
|
36
|
+
updatedAt: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface FinanceReportPeriod {
|
|
40
|
+
kind: 'month' | 'quarter' | 'custom';
|
|
41
|
+
selector: string;
|
|
42
|
+
label: string;
|
|
43
|
+
timezone: string;
|
|
44
|
+
start: string;
|
|
45
|
+
end: string;
|
|
46
|
+
effectiveEnd: string;
|
|
47
|
+
periodToDate: boolean;
|
|
48
|
+
cutoff: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface FinanceReportTotals {
|
|
52
|
+
currency: string;
|
|
53
|
+
credits: string;
|
|
54
|
+
debits: string;
|
|
55
|
+
net: string;
|
|
56
|
+
rows: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface FinanceReport {
|
|
60
|
+
id: string;
|
|
61
|
+
revision: number;
|
|
62
|
+
supersedesReportId: string | null;
|
|
63
|
+
supersededByReportId: string | null;
|
|
64
|
+
jobId: string | null;
|
|
65
|
+
period: FinanceReportPeriod;
|
|
66
|
+
scope: 'all' | 'business' | 'personal';
|
|
67
|
+
accountIds: string[];
|
|
68
|
+
includeHidden: boolean;
|
|
69
|
+
includePending: boolean;
|
|
70
|
+
strict: boolean;
|
|
71
|
+
status: ReportStatus;
|
|
72
|
+
local_export_complete: boolean | null;
|
|
73
|
+
provider_coverage: ProviderCoverage | null;
|
|
74
|
+
reconciliation_status: ReconciliationStatus;
|
|
75
|
+
datasetHash: string | null;
|
|
76
|
+
rowCount: number | null;
|
|
77
|
+
pendingCount: number | null;
|
|
78
|
+
totals: FinanceReportTotals[] | null;
|
|
79
|
+
warnings: string[];
|
|
80
|
+
rendererVersion: string | null;
|
|
81
|
+
errorCode: string | null;
|
|
82
|
+
errorMessage: string | null;
|
|
83
|
+
artifacts: Array<{ format: ReportFormat; bytes: number; sha256: string }>;
|
|
84
|
+
createdAt: string;
|
|
85
|
+
generatedAt: string | null;
|
|
86
|
+
notice: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface BinaryResponse {
|
|
90
|
+
bytes: Uint8Array;
|
|
91
|
+
contentType: string;
|
|
92
|
+
filename: string | null;
|
|
93
|
+
sha256: string | null;
|
|
94
|
+
headers: Record<string, string>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface FinanceStatement {
|
|
98
|
+
id: string;
|
|
99
|
+
accountId: string;
|
|
100
|
+
institutionLabel: string | null;
|
|
101
|
+
label: string;
|
|
102
|
+
cycle: 'monthly' | 'quarterly' | 'custom';
|
|
103
|
+
periodStart: string;
|
|
104
|
+
periodEnd: string;
|
|
105
|
+
timezone: string;
|
|
106
|
+
notes: string | null;
|
|
107
|
+
originalFilename: string | null;
|
|
108
|
+
contentType: string;
|
|
109
|
+
bytes: number;
|
|
110
|
+
sha256: string;
|
|
111
|
+
scanState: 'quarantined' | 'clean' | 'rejected';
|
|
112
|
+
scanReason: string | null;
|
|
113
|
+
provenance: string;
|
|
114
|
+
verified: false;
|
|
115
|
+
reconciliation: FinanceReconciliation | null;
|
|
116
|
+
createdAt: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface FinanceReconciliation {
|
|
120
|
+
id: string;
|
|
121
|
+
statementId: string;
|
|
122
|
+
reportId: string;
|
|
123
|
+
accountId: string;
|
|
124
|
+
currency: string;
|
|
125
|
+
entered: { opening: string; closing: string; credits: string | null; debits: string | null };
|
|
126
|
+
signConvention: 'as_stated' | 'liability_positive';
|
|
127
|
+
normalized: { opening: string; closing: string };
|
|
128
|
+
expectedClosing: string;
|
|
129
|
+
difference: string;
|
|
130
|
+
state: 'matched' | 'mismatch' | 'unavailable' | 'user_reconciled' | 'invalidated';
|
|
131
|
+
acknowledged: boolean;
|
|
132
|
+
datasetHash: string | null;
|
|
133
|
+
version: number;
|
|
134
|
+
createdAt: string;
|
|
135
|
+
invalidatedAt: string | null;
|
|
136
|
+
bankVerified: false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface AccountCoverage {
|
|
140
|
+
accountId: string;
|
|
141
|
+
name: string | null;
|
|
142
|
+
org_name: string | null;
|
|
143
|
+
currency: string | null;
|
|
144
|
+
coverage: ProviderCoverage;
|
|
145
|
+
fraction: number;
|
|
146
|
+
gaps: Array<{ start: string; end: string }>;
|
|
147
|
+
warnings: string[];
|
|
148
|
+
capped: boolean;
|
|
149
|
+
rowsRejected: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface PeriodSelection {
|
|
153
|
+
period?: string;
|
|
154
|
+
from?: string;
|
|
155
|
+
to?: string;
|
|
156
|
+
timezone?: string;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function connectSimpleFin(
|
|
160
|
+
client: CoinPayClient,
|
|
161
|
+
options: { setupToken: string; label?: string; protocolVersion?: 1 | 2; idempotencyKey?: string },
|
|
162
|
+
): Promise<{ connection: Record<string, unknown>; replayed?: boolean }>;
|
|
163
|
+
export function disconnectFinanceConnection(client: CoinPayClient, connectionId: string): Promise<{ connection: Record<string, unknown>; note: string }>;
|
|
164
|
+
export function describeFinanceConnection(
|
|
165
|
+
client: CoinPayClient,
|
|
166
|
+
connectionId: string,
|
|
167
|
+
): Promise<{ connection: Record<string, unknown>; deletionWouldRemove: { accounts: number; transactions: number; statements: number; reports: number } }>;
|
|
168
|
+
export function deleteFinanceConnection(client: CoinPayClient, connectionId: string, options: { confirm: true }): Promise<{ success: boolean; removed: Record<string, number> }>;
|
|
169
|
+
export function setFinanceSyncConsent(client: CoinPayClient, connectionId: string, dailySync: boolean): Promise<{ connection: Record<string, unknown> }>;
|
|
170
|
+
|
|
171
|
+
export function createBackfillJob(
|
|
172
|
+
client: CoinPayClient,
|
|
173
|
+
options: PeriodSelection & { connectionId?: string; idempotencyKey?: string },
|
|
174
|
+
): Promise<{ jobs: FinanceJob[]; job: FinanceJob; timezone?: { timezone: string; source: 'request' | 'saved' } }>;
|
|
175
|
+
export function createRefreshJob(client: CoinPayClient, options: { connectionId: string; days?: number; idempotencyKey?: string }): Promise<{ jobs: FinanceJob[]; job: FinanceJob }>;
|
|
176
|
+
export function getFinanceJob(client: CoinPayClient, jobId: string): Promise<FinanceJob>;
|
|
177
|
+
export function listFinanceJobs(client: CoinPayClient, options?: { limit?: number; connectionId?: string }): Promise<FinanceJob[]>;
|
|
178
|
+
export function cancelFinanceJob(client: CoinPayClient, jobId: string): Promise<FinanceJob>;
|
|
179
|
+
export function waitForFinanceJob(
|
|
180
|
+
client: CoinPayClient,
|
|
181
|
+
jobId: string,
|
|
182
|
+
options?: { intervalMs?: number; timeoutMs?: number; onProgress?: (job: FinanceJob) => void; sleep?: (ms: number) => Promise<void> },
|
|
183
|
+
): Promise<FinanceJob>;
|
|
184
|
+
|
|
185
|
+
export function getFinanceCoverage(
|
|
186
|
+
client: CoinPayClient,
|
|
187
|
+
options: PeriodSelection & { accountIds?: string[]; includeHidden?: boolean },
|
|
188
|
+
): Promise<{ period: FinanceReportPeriod; provider_coverage: ProviderCoverage; accounts: AccountCoverage[] }>;
|
|
189
|
+
|
|
190
|
+
export function createFinanceReport(
|
|
191
|
+
client: CoinPayClient,
|
|
192
|
+
options: PeriodSelection & {
|
|
193
|
+
accountIds?: string[];
|
|
194
|
+
scope?: 'all' | 'business' | 'personal';
|
|
195
|
+
includeHidden?: boolean;
|
|
196
|
+
includePendingAppendix?: boolean;
|
|
197
|
+
formats?: ReportFormat[];
|
|
198
|
+
strict?: boolean;
|
|
199
|
+
idempotencyKey?: string;
|
|
200
|
+
},
|
|
201
|
+
): Promise<{ report: FinanceReport; job: FinanceJob }>;
|
|
202
|
+
export function listFinanceReports(client: CoinPayClient, options?: { limit?: number; offset?: number }): Promise<{ reports: FinanceReport[]; total: number }>;
|
|
203
|
+
export function getFinanceReport(client: CoinPayClient, reportId: string): Promise<{ report: FinanceReport; job: FinanceJob | null }>;
|
|
204
|
+
export function deleteFinanceReport(client: CoinPayClient, reportId: string): Promise<{ success: boolean; note: string }>;
|
|
205
|
+
export function waitForFinanceReport(
|
|
206
|
+
client: CoinPayClient,
|
|
207
|
+
reportId: string,
|
|
208
|
+
options?: { intervalMs?: number; timeoutMs?: number; onProgress?: (data: { report: FinanceReport; job: FinanceJob | null }) => void; sleep?: (ms: number) => Promise<void> },
|
|
209
|
+
): Promise<{ report: FinanceReport; job: FinanceJob | null }>;
|
|
210
|
+
export function downloadFinanceReport(client: CoinPayClient, reportId: string, options?: { format?: ReportFormat }): Promise<BinaryResponse>;
|
|
211
|
+
|
|
212
|
+
export function importFinanceStatement(
|
|
213
|
+
client: CoinPayClient,
|
|
214
|
+
options: PeriodSelection & {
|
|
215
|
+
file: Uint8Array | Blob;
|
|
216
|
+
filename?: string;
|
|
217
|
+
accountId: string;
|
|
218
|
+
institutionLabel?: string;
|
|
219
|
+
cycle?: 'monthly' | 'quarterly' | 'custom';
|
|
220
|
+
notes?: string;
|
|
221
|
+
},
|
|
222
|
+
): Promise<{ statement: FinanceStatement; duplicateOf: string | null; note: string }>;
|
|
223
|
+
export function listFinanceStatements(
|
|
224
|
+
client: CoinPayClient,
|
|
225
|
+
options?: PeriodSelection & { accountId?: string; limit?: number },
|
|
226
|
+
): Promise<FinanceStatement[]>;
|
|
227
|
+
export function getFinanceStatement(client: CoinPayClient, statementId: string): Promise<{ statement: FinanceStatement; reconciliations: FinanceReconciliation[] }>;
|
|
228
|
+
export function downloadFinanceStatement(client: CoinPayClient, statementId: string): Promise<BinaryResponse>;
|
|
229
|
+
export function deleteFinanceStatement(client: CoinPayClient, statementId: string): Promise<{ success: boolean; note: string }>;
|
|
230
|
+
export function reconcileFinanceStatement(
|
|
231
|
+
client: CoinPayClient,
|
|
232
|
+
statementId: string,
|
|
233
|
+
options: {
|
|
234
|
+
reportId: string;
|
|
235
|
+
opening: string;
|
|
236
|
+
closing: string;
|
|
237
|
+
credits?: string;
|
|
238
|
+
debits?: string;
|
|
239
|
+
currency: string;
|
|
240
|
+
signConvention?: 'as_stated' | 'liability_positive';
|
|
241
|
+
acknowledge?: boolean;
|
|
242
|
+
},
|
|
243
|
+
): Promise<FinanceReconciliation>;
|
|
244
|
+
|
|
245
|
+
export interface BooksRow {
|
|
246
|
+
id: string;
|
|
247
|
+
accountId: string;
|
|
248
|
+
accountName: string;
|
|
249
|
+
orgName: string | null;
|
|
250
|
+
currency: string;
|
|
251
|
+
posted: string | null;
|
|
252
|
+
amount: string;
|
|
253
|
+
payee: string | null;
|
|
254
|
+
description: string | null;
|
|
255
|
+
memo: string | null;
|
|
256
|
+
category: string | null;
|
|
257
|
+
categorySource: 'auto' | 'rule' | 'model' | 'user';
|
|
258
|
+
categoryConfidence: number | null;
|
|
259
|
+
taxCategory: string | null;
|
|
260
|
+
taxCategoryLabel: string;
|
|
261
|
+
scope: 'business' | 'personal' | string;
|
|
262
|
+
scopeOverride: string | null;
|
|
263
|
+
accountScope: string;
|
|
264
|
+
reviewedAt: string | null;
|
|
265
|
+
note: string | null;
|
|
266
|
+
suggestion: { category: string | null; taxCategory: string | null; confidence: number | null; by: string | null } | null;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface BooksRule {
|
|
270
|
+
id: string;
|
|
271
|
+
match_field: 'payee' | 'description';
|
|
272
|
+
match_type: 'exact' | 'contains';
|
|
273
|
+
pattern: string;
|
|
274
|
+
category: string;
|
|
275
|
+
tax_category: string | null;
|
|
276
|
+
scope: 'business' | 'personal' | null;
|
|
277
|
+
hits: number;
|
|
278
|
+
active: boolean;
|
|
279
|
+
created_at: string;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export interface BooksSummaryLine {
|
|
283
|
+
taxCategory: string;
|
|
284
|
+
label: string;
|
|
285
|
+
currency: string;
|
|
286
|
+
total: string;
|
|
287
|
+
rows: number;
|
|
288
|
+
excluded: boolean;
|
|
289
|
+
income: boolean;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export function listBooksQueue(
|
|
293
|
+
client: CoinPayClient,
|
|
294
|
+
options?: { status?: 'unreviewed' | 'reviewed' | 'all'; scope?: 'business' | 'personal' | 'all'; accountId?: string; search?: string; start?: string; end?: string; limit?: number; offset?: number },
|
|
295
|
+
): Promise<{ rows: BooksRow[]; total: number; unreviewed: number; categories: string[]; taxCategories: Array<{ id: string; label: string }>; modelEnabled: boolean }>;
|
|
296
|
+
export function reviewBooksTransaction(
|
|
297
|
+
client: CoinPayClient,
|
|
298
|
+
transactionId: string,
|
|
299
|
+
options?: { category?: string | null; taxCategory?: string | null; scope?: 'business' | 'personal' | null; note?: string | null; createRule?: boolean },
|
|
300
|
+
): Promise<BooksRow>;
|
|
301
|
+
export function bulkReviewBooks(
|
|
302
|
+
client: CoinPayClient,
|
|
303
|
+
ids: string[],
|
|
304
|
+
options?: { category?: string | null; taxCategory?: string | null; scope?: 'business' | 'personal' | null; createRule?: boolean },
|
|
305
|
+
): Promise<{ reviewed: number }>;
|
|
306
|
+
export function categorizeBooks(client: CoinPayClient, options?: { useModel?: boolean; onlyUncategorized?: boolean }): Promise<{ job: FinanceJob; modelEnabled: boolean }>;
|
|
307
|
+
export function listBooksRules(client: CoinPayClient): Promise<BooksRule[]>;
|
|
308
|
+
export function createBooksRule(
|
|
309
|
+
client: CoinPayClient,
|
|
310
|
+
options: { matchField?: 'payee' | 'description'; matchType?: 'exact' | 'contains'; pattern: string; category: string; taxCategory?: string | null; scope?: 'business' | 'personal' | null },
|
|
311
|
+
): Promise<BooksRule>;
|
|
312
|
+
export function deleteBooksRule(client: CoinPayClient, ruleId: string): Promise<{ success: boolean }>;
|
|
313
|
+
export function getBooksSummary(
|
|
314
|
+
client: CoinPayClient,
|
|
315
|
+
options?: PeriodSelection & { scope?: 'business' | 'personal' | 'all'; rows?: boolean },
|
|
316
|
+
): Promise<{ period: Record<string, unknown>; scope: string; lines: BooksSummaryLine[]; totals: Array<{ currency: string; income: string; expenses: string; net: string; excluded: string }>; rows: number; unreviewed: number; uncategorized: number; notice: string; transactions?: BooksRow[] }>;
|
|
317
|
+
export function exportBooks(client: CoinPayClient, options?: PeriodSelection & { scope?: 'business' | 'personal' | 'all'; format?: 'csv' | 'pdf' | 'html' | 'json' }): Promise<BinaryResponse>;
|
|
318
|
+
export function listFinancePayloads(client: CoinPayClient, options?: { connectionId?: string; limit?: number; offset?: number }): Promise<{ payloads: Array<Record<string, unknown>>; total: number }>;
|
|
319
|
+
export function downloadFinancePayload(client: CoinPayClient, payloadId: string): Promise<BinaryResponse>;
|
|
320
|
+
|
|
321
|
+
export interface SendOutcome {
|
|
322
|
+
sent: string[];
|
|
323
|
+
failed: Array<{ to: string; error: string }>;
|
|
324
|
+
attached: string[];
|
|
325
|
+
linkUrl: string;
|
|
326
|
+
linkExpiresAt: string;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export interface WeeklyDigest {
|
|
330
|
+
id: string;
|
|
331
|
+
kind: 'weekly_digest';
|
|
332
|
+
weekdays: number[];
|
|
333
|
+
hour: number;
|
|
334
|
+
timezone: string;
|
|
335
|
+
recipients: string[];
|
|
336
|
+
scope: 'business' | 'personal' | 'all';
|
|
337
|
+
formats: string[];
|
|
338
|
+
active: boolean;
|
|
339
|
+
lastSentAt: string | null;
|
|
340
|
+
nextRunAt: string | null;
|
|
341
|
+
createdAt: string;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
export function sendFinanceReportEmail(
|
|
345
|
+
client: CoinPayClient,
|
|
346
|
+
reportId: string,
|
|
347
|
+
options: { to: string | string[]; formats?: ReportFormat[]; message?: string | null; attach?: boolean; expiresInDays?: number },
|
|
348
|
+
): Promise<SendOutcome>;
|
|
349
|
+
export function sendBooksEmail(
|
|
350
|
+
client: CoinPayClient,
|
|
351
|
+
options: { to: string | string[]; period?: string; from?: string; toDate?: string; timezone?: string; scope?: 'business' | 'personal' | 'all'; formats?: string[]; message?: string | null; attach?: boolean; expiresInDays?: number },
|
|
352
|
+
): Promise<SendOutcome & { unreviewed: number; rows: number }>;
|
|
353
|
+
export function getWeeklyDigest(client: CoinPayClient): Promise<WeeklyDigest | null>;
|
|
354
|
+
export function setWeeklyDigest(
|
|
355
|
+
client: CoinPayClient,
|
|
356
|
+
options?: { weekdays?: number[]; hour?: number; timezone?: string; recipients?: string[]; scope?: 'business' | 'personal' | 'all'; formats?: string[]; active?: boolean },
|
|
357
|
+
): Promise<WeeklyDigest>;
|
|
358
|
+
export function deleteWeeklyDigest(client: CoinPayClient): Promise<{ success: boolean }>;
|
|
359
|
+
export function sendWeeklyDigestNow(client: CoinPayClient): Promise<SendOutcome>;
|